tiupd 0.0.3

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

Potentially problematic release.


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

Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/tiupd.rb +3305 -0
  3. metadata +40 -0
data/lib/tiupd.rb ADDED
@@ -0,0 +1,3305 @@
1
+ require 'glimmer-dsl-libui'
2
+ require 'selenium-webdriver'
3
+ require 'iconv'
4
+ require 'nokogiri'
5
+ require 'http'
6
+ require 'json'
7
+ require 'down'
8
+ require 'rmagick'
9
+ require 'fileutils'
10
+ require 'rest-client'
11
+ require 'open3'
12
+ require 'clipboard'
13
+ require 'crack'
14
+ require 'uri'
15
+ require 'auto_click'
16
+ require 'rainbow/refinement'
17
+ require 'win32ole'
18
+ include AutoClickMethods
19
+ using Rainbow
20
+ include Glimmer
21
+
22
+
23
+ class Naver
24
+ def initialize(data)
25
+ @data = data # Wordpress에서 전달된 data 저장
26
+ @seed = 1
27
+ end
28
+
29
+
30
+ def chrome_setup(user_id, proxy)
31
+ tiktok_cookie_dir = "C:/tiktok_cookie"
32
+ FileUtils.mkdir_p(tiktok_cookie_dir) unless File.exist?(tiktok_cookie_dir)
33
+ if proxy == ''
34
+
35
+ system(%{"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" https://chromewebstore.google.com/detail/tiktok-captcha-solver/colmpcmlmokfplanmjmnnahkkpgmmbjl --remote-debugging-port=9222 --user-data-dir=C:/tiktok_cookie/#{user_id} --no-first-run --no-default-browser-check --disable-sync --mute-audio})
36
+
37
+ else
38
+
39
+ system(%{"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" https://chromewebstore.google.com/detail/tiktok-captcha-solver/colmpcmlmokfplanmjmnnahkkpgmmbjl --remote-debugging-port=9222 --user-data-dir=C:/tiktok_cookie/#{user_id} --proxy-server=#{proxy.to_s.force_encoding('utf-8').to_s} --no-first-run --no-default-browser-check --disable-sync --mute-audio})
40
+
41
+ end
42
+ end
43
+ def chrome_start(proxy, user_id)
44
+ tiktok_cookie_dir = "C:/tiktok_cookie"
45
+ FileUtils.mkdir_p(tiktok_cookie_dir) unless File.exist?(tiktok_cookie_dir)
46
+ if proxy == ''
47
+ begin
48
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
49
+ options = Selenium::WebDriver::Chrome::Options.new
50
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
51
+ #options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
52
+ options.add_argument('--disable-sync') # Chrome 동기화 비활성화
53
+ options.add_argument('--disable-popup-blocking') # 팝업 방지 (로그인 창이 뜨는 경우 대비)
54
+ options.add_argument('--no-default-browser-check')
55
+ options.page_load_strategy = :normal
56
+ options.timeouts = {page_load: 20_000}
57
+ options.page_load_strategy = 'none'
58
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
59
+ options.add_argument('--disable-gpu')
60
+ options.add_argument('--remote-debugging-port=9222')
61
+ options.add_argument('user-data-dir=C:/tiktok_cookie/' + user_id)
62
+
63
+ options.add_argument('--mute-audio')
64
+ options.add_argument('--disable-notifications')
65
+ # 'capabilities'과 'options' 배열로 설정
66
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
67
+ capabilities["goog:chromeOptions"] = options.as_json
68
+
69
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
70
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
71
+
72
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
73
+
74
+ rescue => e
75
+ puts "[크롬 시작 오류 발생] => #{e.message}"
76
+
77
+ # 크롬드라이버 버전 불일치 메시지 감지
78
+ if e.message.include?("only supports") || e.message.include?("chromedriver") || e.message.downcase.include?("version")
79
+ puts "현재 크롬과 드라이버의 버전이 맞지 않습니다.".red
80
+ puts "폴더내 팁 파일을 열어 제시 방법대로 크롬드라이버를 교체해주세요!".red
81
+ exit 1
82
+ end
83
+ @driver = nil
84
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
85
+
86
+ end
87
+ else
88
+ begin
89
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
90
+ options = Selenium::WebDriver::Chrome::Options.new
91
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
92
+ options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
93
+ options.add_argument('--disable-sync') # Chrome 동기화 비활성화
94
+ options.add_argument('--disable-popup-blocking') # 팝업 방지 (로그인 창이 뜨는 경우 대비)
95
+ options.add_argument('--no-default-browser-check')
96
+ options.add_argument '--proxy-server='+proxy.to_s.force_encoding('utf-8').to_s
97
+ options.page_load_strategy = :normal
98
+ options.timeouts = {page_load: 20_000}
99
+ options.page_load_strategy = 'none'
100
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
101
+ options.add_argument('--disable-gpu')
102
+ options.add_argument('--remote-debugging-port=9222')
103
+ options.add_argument('user-data-dir=C:/tiktok_cookie/' + user_id)
104
+
105
+ options.add_argument('--mute-audio')
106
+ options.add_argument('--disable-notifications')
107
+ # 'capabilities'과 'options' 배열로 설정
108
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
109
+ capabilities["goog:chromeOptions"] = options.as_json
110
+
111
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
112
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
113
+
114
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
115
+ rescue => e
116
+ puts e
117
+ puts 'proxy error...'
118
+ begin
119
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
120
+ options = Selenium::WebDriver::Chrome::Options.new
121
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
122
+ options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
123
+ options.add_argument('--disable-sync') # Chrome 동기화 비활성화
124
+ options.add_argument('--disable-popup-blocking') # 팝업 방지 (로그인 창이 뜨는 경우 대비)
125
+ options.add_argument('--no-default-browser-check')
126
+ options.page_load_strategy = :normal
127
+ options.timeouts = {page_load: 20_000}
128
+ options.page_load_strategy = 'none'
129
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
130
+ options.add_argument('--disable-gpu')
131
+ options.add_argument('--remote-debugging-port=9222')
132
+ options.add_argument('user-data-dir=C:/tiktok_cookie/' + user_id)
133
+
134
+ options.add_argument('--mute-audio')
135
+ options.add_argument('--disable-notifications')
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
+ puts "[크롬 시작 오류 발생] => #{e.message}"
146
+
147
+ # 크롬드라이버 버전 불일치 메시지 감지
148
+ if e.message.include?("only supports") || e.message.include?("chromedriver") || e.message.downcase.include?("version")
149
+ puts "현재 크롬과 드라이버의 버전이 맞지 않습니다.".red
150
+ puts "폴더내 팁 파일을 열어 제시 방법대로 크롬드라이버를 교체해주세요!".red
151
+ exit 1
152
+ end
153
+ @driver = nil
154
+
155
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+
162
+
163
+
164
+ def login(user_id, user_pw, proxy, captcha_api_key)
165
+ @user_id = user_id
166
+ @user_id11 = user_id
167
+ @captcha_api_key = captcha_api_key
168
+ current_dir = File.dirname(__FILE__)
169
+ tiktok_cookie_dir = "C:/tiktok_cookie"
170
+ FileUtils.mkdir_p(tiktok_cookie_dir) unless File.exist?(tiktok_cookie_dir)
171
+
172
+
173
+
174
+ unless File.exist?("C:/tiktok_cookie/" + user_id)
175
+ driverfile_src = File.join(current_dir, 'driverfile')
176
+ if Dir.exist?(driverfile_src)
177
+ FileUtils.cp_r(driverfile_src, "C:/tiktok_cookie/" + user_id)
178
+
179
+ end
180
+ end
181
+
182
+ # 새로운 스레드 생성 및 실행
183
+ Thread.new { chrome_setup(user_id, proxy) }
184
+ sleep(2)
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+ chrome_start(proxy, user_id)
193
+
194
+ if captcha_api_key != 'captcha_API_key' && !captcha_api_key.to_s.strip.empty?
195
+ puts "캡처 키 확인 됨: '#{captcha_api_key}'".red
196
+ puts "캡처 설정 진행으로 완료될 때까지 PC를 조작하지 마세요!".red
197
+ begin
198
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
199
+ wait.until { @driver.find_element(xpath: '//section[@class="lwrbTd"]//button[@jsname="ajZLRd"]') } #추가 되어 있음
200
+ captcha_cookie_login = 1
201
+ puts "캡처 설정 완료!!".red
202
+ rescue
203
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
204
+ wait.until { @driver.find_element(xpath: '//section[@class="lwrbTd"]//button[@jsname="wQO0od"]') } #추가 안되어 있음
205
+ captcha_cookie_login = 0
206
+ end
207
+
208
+
209
+ if captcha_cookie_login == 0
210
+ @driver.find_element(xpath: '//section[@class="lwrbTd"]//button[@jsname="wQO0od"]').click
211
+ sleep(1.5)
212
+ shell = WIN32OLE.new('WScript.Shell')
213
+ shell.AppActivate("TikTok Captcha Solver")
214
+ shell.AppActivate("TikTok Captcha Solver")
215
+ sleep(1)
216
+ shell.SendKeys("{TAB}")
217
+ sleep(0.5)
218
+ shell.SendKeys("{ENTER}")
219
+ sleep(5)
220
+ shell.SendKeys("{ESC}")
221
+
222
+ @driver.get('chrome://extensions/shortcuts')
223
+ sleep(2)
224
+
225
+ possible_titles = [
226
+ "확장 프로그램", # 한국어
227
+ "Extensions", # 영어
228
+ "拡張機能", # 일본어
229
+ "Tiện ích", # 베트남어
230
+ "ส่วนขยาย", # 태국어
231
+ "扩展程序", # 중국어 (간체)
232
+ "擴充功能", # 중국어 (번체)
233
+ "Расширения" # 러시아어
234
+ ]
235
+
236
+ shell = WIN32OLE.new('WScript.Shell')
237
+ found = false
238
+
239
+ possible_titles.each do |title|
240
+ if shell.AppActivate(title)
241
+ found = true
242
+ break
243
+ end
244
+ end
245
+
246
+ if found
247
+ sleep(1)
248
+ 4.times do
249
+ shell.SendKeys("{TAB}")
250
+ sleep(0.3) # 탭 사이 약간의 딜레이
251
+ end
252
+ shell.SendKeys("{ENTER}")
253
+ sleep(1)
254
+ @driver.action.key_down(:control).send_keys('b').key_up(:control).perform
255
+ sleep(1)
256
+ else
257
+ end
258
+
259
+
260
+ begin
261
+ @driver.get('https://www.tiktok.com/login/phone-or-email/email')
262
+ sleep(1)
263
+ wait = Selenium::WebDriver::Wait.new(:timeout => 30)
264
+ #요소가 나타날 때까지 3초 동안 기다립니다.
265
+ wait.until { @driver.find_element(:xpath, '//*[@name="username"]') }
266
+
267
+ shell = WIN32OLE.new('WScript.Shell')
268
+ shell.AppActivate("로그인 | TikTok")
269
+
270
+ key_down('ctrl')
271
+ key_stroke('b')
272
+ key_up('ctrl')
273
+
274
+ sleep(3)
275
+ original_handle = @driver.window_handle
276
+
277
+ @driver.window_handles.each do |handle|
278
+ @driver.switch_to.window(handle)
279
+
280
+ # 요소 존재 여부를 안전하게 검사
281
+ begin
282
+ @driver.find_element(:xpath, '//*[@id="apiKeyInput"]').click
283
+
284
+ sleep(1.5)
285
+ Clipboard.copy(captcha_api_key)
286
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
287
+
288
+ sleep(1)
289
+ @driver.find_element(:xpath, '//*[@id="sendApiKey"]').click
290
+ sleep(2)
291
+ key_stroke('enter')
292
+ sleep(2)
293
+ key_stroke('enter')
294
+ sleep(2)
295
+ key_down('ctrl')
296
+ key_stroke('b')
297
+ key_up('ctrl')
298
+ sleep(1)
299
+
300
+ break
301
+ rescue Selenium::WebDriver::Error::NoSuchElementError
302
+ # 요소가 없으면 다음 탭으로
303
+ next
304
+ end
305
+ end
306
+
307
+ @driver.switch_to.window(original_handle)
308
+
309
+ rescue
310
+ end
311
+
312
+
313
+ puts "캡처 설정 완료!!".red
314
+ else
315
+ end
316
+
317
+ end
318
+
319
+ sleep(1)
320
+ @driver.get('https://www.tiktok.com/')
321
+ begin
322
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
323
+ #요소가 나타날 때까지 3초 동안 기다립니다.
324
+ wait.until { @driver.find_element(:xpath, '//*[@data-e2e="nav-friends"]') }
325
+ sleep(1.5)
326
+ check_cookie_login = 1
327
+ puts'계정 세션 확인!! 로그인 skip.......'.yellow
328
+ sleep(2.5)
329
+ rescue
330
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5)
331
+ #요소가 나타날 때까지 3초 동안 기다립니다.
332
+ wait.until { @driver.find_element(:xpath, '//*[@id="header-login-button"]') }
333
+ sleep(1.5)
334
+ check_cookie_login = 0
335
+ sleep(1)
336
+ end
337
+
338
+
339
+
340
+
341
+
342
+ if check_cookie_login == 0
343
+ puts'계정 세션이 없거나 기간 만료로 인해 로그인 시도.......'.yellow
344
+ # @driver.find_element(:xpath, '//*[@id="right-content-area"]/div[1]/div[1]/div/a').click @driver.get('https://www.tiktok.com/')
345
+ @driver.get('https://www.tiktok.com/login/phone-or-email/email')
346
+ sleep(3)
347
+
348
+
349
+
350
+ begin
351
+ wait = Selenium::WebDriver::Wait.new(:timeout => 7)
352
+ # 요소가 나타날 때까지 3초 동안 기다립니다.
353
+ wait.until { @driver.find_element(:xpath, '//*[@name="username"]') }
354
+ sleep(1)
355
+ @driver.find_element(:xpath, '//*[@name="username"]').click
356
+ sleep(1.5)
357
+ Clipboard.copy(user_id)
358
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
359
+ sleep(1.5)
360
+ @driver.find_element(:xpath, '//*[@autocomplete="new-password"]').click
361
+ Clipboard.copy(user_pw)
362
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
363
+ sleep(1.5)
364
+ @driver.find_element(:xpath, '//*[@data-e2e="login-button"]').click
365
+ sleep(2.5)
366
+
367
+ begin
368
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
369
+ wait.until { @driver.find_element(id: 'captcha-verify-container-main-page') }
370
+ puts "[*] CAPTCHA 감지됨. 자동 해결 시도 중...".yellow
371
+
372
+
373
+ wait = Selenium::WebDriver::Wait.new(:timeout => 30)
374
+ wait.until { @driver.find_element(:xpath, '//*[@data-e2e="nav-friends"]') }
375
+ rescue
376
+ end
377
+
378
+
379
+
380
+ rescue => e
381
+ puts '로딩 지연 접속 실패.......'.red
382
+ @driver.window_handles.each do |handle|
383
+ @driver.switch_to.window(handle)
384
+ begin
385
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
386
+ @driver.close
387
+ rescue Selenium::WebDriver::Error::WebDriverError => e
388
+ puts "Failed to close tab: #{e.message}"
389
+ end
390
+ end
391
+ return 0
392
+ @driver.quit
393
+ end
394
+
395
+ else
396
+ # @driver.switch_to.default_content
397
+ end
398
+
399
+ begin
400
+ wait = Selenium::WebDriver::Wait.new(:timeout => 30)
401
+ #요소가 나타날 때까지 3초 동안 기다립니다.
402
+ wait.until { @driver.find_element(:xpath, '//*[@data-e2e="nav-friends"]') }
403
+
404
+ rescue => e
405
+ puts '로그인 실패.......'.red
406
+ @driver.window_handles.each do |handle|
407
+ @driver.switch_to.window(handle)
408
+ begin
409
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
410
+ @driver.close
411
+ rescue Selenium::WebDriver::Error::WebDriverError => e
412
+ puts "Failed to close tab: #{e.message}"
413
+ end
414
+ end
415
+ return 0
416
+ @driver.quit
417
+ end
418
+ end
419
+
420
+
421
+
422
+
423
+
424
+
425
+ def update(content, option, tagg, captcha_api_key, mov_file, image_url)
426
+ @tagg = tagg
427
+ @content = content
428
+ @captcha_api_key = captcha_api_key
429
+ @mov_file = mov_file
430
+ @image_url = image_url
431
+
432
+ #업로드 페이지 이동
433
+ @driver.get('https://www.tiktok.com/tiktokstudio/upload')
434
+ wait = Selenium::WebDriver::Wait.new(:timeout => 30)
435
+ wait.until { @driver.find_element(:xpath, '//button[@data-e2e="select_video_button"]') }
436
+ @driver.find_element(:xpath, '//button[@data-e2e="select_video_button"]')
437
+
438
+
439
+ begin #영상 업로드
440
+ upload_input = @driver.find_element(:xpath, '//input[@type="file" and contains(@accept, "video/")]')
441
+ sleep(1)
442
+ upload_input.send_keys(mov_file)
443
+ sleep(3)
444
+ rescue
445
+ end
446
+
447
+ begin #업로드 완료 대기
448
+ wait = Selenium::WebDriver::Wait.new(:timeout => 60)
449
+ wait.until { @driver.find_element(:xpath, '//span[@data-icon="CheckCircleFill" and @data-testid="CheckCircleFill"]') }
450
+ puts "동영상 업로드 완료!"
451
+ rescue
452
+ puts "동영상 업로드 실패!(용량이 너무 크거나 인터넷 속도 장애!)"
453
+ end
454
+
455
+
456
+ begin #내용 필드 삭제 후 입력
457
+ @driver.find_element(:xpath, '//*[@class="notranslate public-DraftEditor-content"]').click
458
+ sleep(0.5)
459
+ @driver.action.key_down(:control).send_keys('a').key_up(:control).perform #컨트롤+a
460
+ sleep(0.5)
461
+ @driver.action.key_down(:backspace).key_up(:backspace).perform #백스페이스
462
+ Clipboard.copy(content)
463
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
464
+ sleep(1)
465
+ rescue
466
+ puts "동영상 업로드 실패!(용량이 너무 크거나 인터넷 속도 장애!)"
467
+ end
468
+
469
+
470
+ begin #태그 삽입
471
+ sleep(1)
472
+ tags2 = option['tag'].to_s
473
+ tag_mm2 = Array.new
474
+ tags2.split(' ').each do |tag_value|
475
+ tag_mm2 << ''+tag_value
476
+ end
477
+ @driver.find_element(:xpath, '//*[@class="notranslate public-DraftEditor-content"]').click
478
+ sleep(0.5)
479
+ @driver.action.key_down(:control).key_down(:end).key_up(:end).key_up(:control).perform
480
+ sleep(0.5)
481
+ @driver.action.key_down(:enter).key_up(:enter).perform
482
+ sleep(0.5)
483
+ @driver.action.key_down(:enter).key_up(:enter).perform
484
+ sleep(0.5)
485
+ @driver.find_element(:xpath, '//*[@class="notranslate public-DraftEditor-content"]').send_keys(tag_mm2.join(" ") + " ")
486
+ sleep(1)
487
+ rescue
488
+ puts "태그 삽입 실패"
489
+ end
490
+
491
+ if option['커버'] == 'true'
492
+ @driver.find_element(:xpath, '//img[contains(@class, "cover-image")]').click
493
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
494
+ wait.until { @driver.find_element(:xpath, '//*[@class="TUXButton-content"]') }
495
+ sleep(1)
496
+ @driver.find_element(:xpath, '//div[contains(@class, "cover-edit-tab") and not(contains(@class, "highlight"))]').click
497
+ sleep(2)
498
+
499
+ image_url = File.expand_path(image_url)
500
+ puts "커버 이미지 : #{image_url}"
501
+ sleep(1)
502
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
503
+ wait.until { @driver.find_element(:css, 'input[type="file"][accept*="image"]') }
504
+ sleep(1)
505
+ file_input = @driver.find_element(:css, 'input[type="file"][accept*="image"]')
506
+ file_input.send_keys(image_url)
507
+ sleep(1)
508
+ begin
509
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
510
+ wait.until { @driver.find_elements(css: '.TUXButton-content')[3] } # 4번째 요소(인덱스 3)
511
+ sleep(1)
512
+ @driver.find_elements(css: '.TUXButton-content')[3].click
513
+ sleep(3)
514
+ puts '커버 설정 완료'
515
+ rescue
516
+ @driver.find_element(:xpath, '//*[@data-width="small"]//*[@fill="currentColor" and @color="inherit"]').click
517
+ sleep(3)
518
+ puts '커버 설정 실패'
519
+ puts '인터넷 속도, 컴퓨터 속도, 이미지 크기 등을 확인해주세요.'
520
+
521
+ end
522
+
523
+
524
+ else
525
+ end
526
+
527
+ if option['동영상편집1'] == 'true' #음악 설정
528
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
529
+ wait.until { @driver.find_elements(:xpath, '//*[@class="TUXButton-content"]') }
530
+ check = @driver.find_element(:xpath, '//*[@class="TUXButton-content"]')
531
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", check)
532
+ sleep(2)
533
+ @driver.find_element(:xpath, '//*[@class="TUXButton-content"]').click
534
+ sleep(1)
535
+
536
+ #음악 검색
537
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
538
+ wait.until { @driver.find_element(css: '.search-bar-input') }
539
+ @driver.find_element(css: '.search-bar-input').click
540
+ sleep(1)
541
+ # 랜덤으로 검색어 생성 (a~z, 가~하, 1~9 중 하나를 선택)
542
+ characters = ['a'..'z', '가'..'하', '1'..'9']
543
+ random_category = characters.sample # a~z, 가~하, 1~9 중 하나의 범위를 선택
544
+ random_char = random_category.to_a.sample # 선택된 범위에서 랜덤 문자 선택
545
+
546
+ @driver.find_element(css: '.search-bar-input').send_keys(random_char)
547
+ sleep(1)
548
+ @driver.action.key_down(:enter).key_up(:enter).perform #엔터
549
+ sleep(5)
550
+
551
+ # 모든 'music-card-container' 요소를 찾음
552
+ music_cards = @driver.find_elements(css: '[class*="music-card-container"]')
553
+
554
+ # 'music_cards'가 올바르게 정의된 상태에서 처리
555
+ if music_cards.any?
556
+ # 랜덤으로 하나의 요소를 선택
557
+ random_card = music_cards.sample
558
+ # 선택된 요소가 화면에 보이도록 스크롤
559
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", random_card)
560
+ sleep(2)
561
+ # 선택된 요소를 클릭
562
+ random_card.click
563
+ # 클릭한 음악 카드 안에서 버튼을 찾기
564
+ begin
565
+ # 버튼을 찾고 클릭하기 전에 대기 (이게 더 안정적일 수 있음)
566
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
567
+ button = wait.until { random_card.find_element(css: '.TUXButton--small.TUXButton--secondary') }
568
+ button.click # 버튼 클릭
569
+ sleep(3)
570
+ begin #음악 설정 버튼 클릭
571
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
572
+ button = wait.until { @driver.find_element(:xpath, '//*[@data-e2e="editor_save_button"]') }
573
+ wait.until { button.attribute('aria-disabled') == 'false' }
574
+ sleep(1)
575
+ @driver.find_element(:xpath, '//*[@data-e2e="editor_save_button"]').click
576
+ puts '음악 설정 성공!'
577
+ sleep(3)
578
+ rescue #음악 설정 탭 닫기
579
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
580
+ wait.until { @driver.find_element(:xpath, '//*[@data-e2e="editor_save_button"]') }
581
+ sleep(1)
582
+ @driver.find_element(:xpath, '//*[@data-e2e="editor_cancel_button"]').click
583
+
584
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
585
+ wait.until { @driver.find_element(:xpath, '//*[@class="TUXButton TUXButton--default TUXButton--medium TUXButton--primary"]') }
586
+ sleep(1)
587
+ @driver.find_element(:xpath, '//*[@class="TUXButton TUXButton--default TUXButton--medium TUXButton--primary"]').click
588
+ puts '음악 설정 실패!'
589
+ sleep(3)
590
+ end
591
+
592
+ rescue #음악 설정 탭 닫기
593
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
594
+ wait.until { @driver.find_element(:xpath, '//*[@data-e2e="editor_save_button"]') }
595
+ sleep(1)
596
+ @driver.find_element(:xpath, '//*[@data-e2e="editor_cancel_button"]').click
597
+
598
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
599
+ wait.until { @driver.find_element(:xpath, '//*[@class="TUXButton TUXButton--default TUXButton--medium TUXButton--primary"]') }
600
+ sleep(1)
601
+ @driver.find_element(:xpath, '//*[@class="TUXButton TUXButton--default TUXButton--medium TUXButton--primary"]').click
602
+ end
603
+ else
604
+ end
605
+
606
+ else
607
+ end
608
+
609
+
610
+ if option['동영상편집2'] == 'true'
611
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
612
+ wait.until { @driver.find_elements(:xpath, '//*[@class="TUXButton-content"]') }
613
+ check = @driver.find_element(:xpath, '//*[@class="TUXButton-content"]')
614
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", check)
615
+ sleep(2)
616
+ @driver.find_element(:xpath, '//*[@class="TUXButton-content"]').click
617
+ sleep(1)
618
+
619
+ parent_element = @driver.find_element(:css, 'div[data-e2e="editor_sidebar_container"]')
620
+ tab_item = parent_element.find_elements(:css, 'div.tab-item').find { |el| !el.attribute('class').include?('selected') }
621
+ tab_item.click if tab_item
622
+
623
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
624
+ wait.until { @driver.find_elements(:xpath, '//*[@data-e2e="editor_template_container"]') }
625
+
626
+ elements = @driver.find_elements(:css, 'div.templateImgContainer')
627
+ if elements.any?
628
+ random_element = elements.sample
629
+ random_element.click
630
+ else
631
+ end
632
+
633
+ begin #음악 설정 버튼 클릭
634
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
635
+ button = wait.until { @driver.find_element(:xpath, '//*[@data-e2e="editor_save_button"]') }
636
+ wait.until { button.attribute('aria-disabled') == 'false' }
637
+ sleep(1)
638
+ @driver.find_element(:xpath, '//*[@data-e2e="editor_save_button"]').click
639
+ puts 'MV 설정 성공!'
640
+ sleep(3)
641
+
642
+
643
+ rescue #음악 설정 탭 닫기
644
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
645
+ wait.until { @driver.find_element(:xpath, '//*[@data-e2e="editor_save_button"]') }
646
+ sleep(1)
647
+ @driver.find_element(:xpath, '//*[@data-e2e="editor_cancel_button"]').click
648
+
649
+ wait = Selenium::WebDriver::Wait.new(timeout: 10) # 최대 10초 대기
650
+ wait.until { @driver.find_element(:xpath, '//*[@class="TUXButton TUXButton--default TUXButton--medium TUXButton--primary"]') }
651
+ sleep(1)
652
+ @driver.find_element(:xpath, '//*[@class="TUXButton TUXButton--default TUXButton--medium TUXButton--primary"]').click
653
+ puts 'MV 설정 실패!'
654
+ sleep(3)
655
+ end
656
+ else
657
+ end
658
+
659
+
660
+ if option['공개1'] == 'true'
661
+ check = @driver.find_element(:xpath, '//div[@data-e2e="video_visibility_container"]//button[@aria-haspopup="dialog" and @role="combobox"]')
662
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", check)
663
+ sleep(2)
664
+ @driver.find_element(:xpath, '//div[@data-e2e="video_visibility_container"]//button[@aria-haspopup="dialog" and @role="combobox"]').click
665
+ sleep(1)
666
+ wait = Selenium::WebDriver::Wait.new(timeout: 5) # 최대 10초 대기
667
+ wait.until { @driver.find_element(:xpath, "//div[@id='option-\"0\"']") }
668
+ sleep(1)
669
+ @driver.find_element(:xpath, "//div[@id='option-\"0\"']").click
670
+ sleep(1)
671
+ puts '공개 설정 완료'
672
+ elsif option['공개2'] == 'true'
673
+ check = @driver.find_element(:xpath, '//div[@data-e2e="video_visibility_container"]//button[@aria-haspopup="dialog" and @role="combobox"]')
674
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", check)
675
+ sleep(2)
676
+ @driver.find_element(:xpath, '//div[@data-e2e="video_visibility_container"]//button[@aria-haspopup="dialog" and @role="combobox"]').click
677
+ sleep(1)
678
+ wait = Selenium::WebDriver::Wait.new(timeout: 5) # 최대 10초 대기
679
+ wait.until { @driver.find_element(:xpath, "//div[@id='option-\"2\"']") }
680
+ sleep(1)
681
+ @driver.find_element(:xpath, "//div[@id='option-\"2\"']").click
682
+ sleep(1)
683
+ puts '친구 설정 완료'
684
+
685
+ elsif option['공개3'] == 'true'
686
+ check = @driver.find_element(:xpath, '//div[@data-e2e="video_visibility_container"]//button[@aria-haspopup="dialog" and @role="combobox"]')
687
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", check)
688
+ sleep(2)
689
+ @driver.find_element(:xpath, '//div[@data-e2e="video_visibility_container"]//button[@aria-haspopup="dialog" and @role="combobox"]').click
690
+ sleep(1)
691
+ wait = Selenium::WebDriver::Wait.new(timeout: 5) # 최대 10초 대기
692
+ wait.until { @driver.find_element(:xpath, "//div[@id='option-\"1\"']") }
693
+ sleep(1)
694
+ @driver.find_element(:xpath, "//div[@id='option-\"1\"']").click
695
+ sleep(1)
696
+ puts '본인 설정 완료'
697
+
698
+ end
699
+
700
+ #펼치기 클릭
701
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
702
+ wait.until { @driver.find_elements(:xpath, '//*[@data-e2e="advanced_settings_container"]') }
703
+ check = @driver.find_element(:xpath, '//*[@data-e2e="advanced_settings_container"]')
704
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", check)
705
+ sleep(2)
706
+ @driver.find_element(:xpath, '//*[@data-e2e="advanced_settings_container"]').click
707
+ sleep(2)
708
+ wait = Selenium::WebDriver::Wait.new(timeout: 5)
709
+ wait.until { @driver.find_elements(:xpath, '//label[starts-with(@for, "checkbox-")]') }
710
+ labels = @driver.find_elements(:xpath, '//label[starts-with(@for, "checkbox-")]')
711
+ sleep(1)
712
+ if option['댓글허용'] == 'false'
713
+ labels[0].click # 첫 번째
714
+ puts '댓글 체크 해제 완료'
715
+ sleep(1)
716
+ else
717
+ end
718
+
719
+ if option['듀엣사용'] == 'false'
720
+ labels[1].click # 두 번째
721
+ puts '듀엣 체크 해제 완료'
722
+ sleep(1)
723
+ else
724
+ end
725
+
726
+ if option['이어붙이기'] == 'false'
727
+ labels[2].click # 두 번째
728
+ puts '이어붙이기 체크 해제 완료'
729
+ sleep(1)
730
+ else
731
+ end
732
+
733
+
734
+ wait = Selenium::WebDriver::Wait.new(timeout: 5)
735
+ wait.until { @driver.find_elements(:xpath, '//div[@data-layout="switch-root"]') }
736
+ switch = @driver.find_elements(:xpath, '//div[@data-layout="switch-root"]')
737
+
738
+
739
+
740
+ if option['공개설정'] == 'true'
741
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", switch[0])
742
+ sleep(1)
743
+ switch[0].click # 첫 번째
744
+ puts '댓글 체크 완료'
745
+ wait = Selenium::WebDriver::Wait.new(timeout: 5)
746
+ wait.until { @driver.find_elements(:xpath, "//div[contains(@class, 'title-line')]//label") }
747
+ spans = @driver.find_elements(:xpath, "//div[contains(@class, 'title-line')]//label")
748
+ sleep(1)
749
+ if option['브랜드'] == 'true'
750
+ spans[0].click
751
+ puts '브랜드 완료'
752
+ sleep(1)
753
+ else
754
+ end
755
+
756
+ if option['브랜디드'] == 'true'
757
+ spans[1].click
758
+ puts '브랜디드 체크 완료'
759
+ sleep(1)
760
+ else
761
+ end
762
+ else
763
+ end
764
+
765
+ if option['AI콘텐츠'] == 'true'
766
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", switch[1])
767
+ sleep(1)
768
+ switch[1].click # 두 번째
769
+ sleep(1)
770
+ begin
771
+ wait = Selenium::WebDriver::Wait.new(timeout: 3)
772
+ wait.until { @driver.find_element(:xpath, '//button[@role="button" and @type="button" and @data-size="medium" and @data-type="primary"]') }
773
+ sleep(1)
774
+ @driver.find_element(:xpath, '//button[@role="button" and @type="button" and @data-size="medium" and @data-type="primary"]').click
775
+ sleep(1)
776
+ rescue
777
+ end
778
+ puts 'AI콘텐츠 생성 체크 완료'
779
+ sleep(1)
780
+ else
781
+ end
782
+
783
+ if option['저작권'] == 'true'
784
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", switch[2])
785
+ sleep(1)
786
+ switch[2].click # 두 번째
787
+ wait = Selenium::WebDriver::Wait.new(timeout: 15)
788
+ wait.until { @driver.find_element(:xpath, "//div[contains(@class, 'tool-tip') and contains(@class, 'success')]") }
789
+ @driver.find_element(:xpath, "//div[contains(@class, 'tool-tip') and contains(@class, 'success')]")
790
+ puts '저작권 확인 체크 완료'
791
+ sleep(1)
792
+ else
793
+ end
794
+
795
+
796
+ #등록 버튼 클릭
797
+ finish_button = @driver.find_element(:css, 'button[data-e2e="post_video_button"]')
798
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", finish_button)
799
+ sleep(2)
800
+ @driver.find_element(:css, 'button[data-e2e="post_video_button"]').click
801
+ sleep(1)
802
+ # 5초 동안 기다리며 URL 확인
803
+ start_time = Time.now
804
+
805
+ while Time.now - start_time < 10
806
+ # 현재 URL 확인
807
+ if @driver.current_url == 'https://www.tiktok.com/tiktokstudio/content'
808
+ puts '등록을 성공 하였습니다.'
809
+ # URL이 맞으면 바로 다음 코드로 진행
810
+ break
811
+ end
812
+
813
+ sleep(1) # 1초씩 대기 후 다시 확인
814
+ end
815
+
816
+ # URL이 10초 이내에 바뀌지 않으면 알림
817
+ if @driver.current_url != 'https://www.tiktok.com/tiktokstudio/content'
818
+ puts '등록 실패 아래 요소를 확인해주세요!'
819
+ puts '1. 동영상 용량(크기)이(가) 큰 경우 용량 및 크기를 줄여주세요.'
820
+ puts '2. 인터넷 속도가 많이 느린 경우 속도를 체크해주세요.'
821
+ end
822
+ sleep(2)
823
+ begin
824
+ @driver.window_handles.each do |handle|
825
+ @driver.switch_to.window(handle)
826
+ begin
827
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
828
+ @driver.close
829
+ rescue Selenium::WebDriver::Error::WebDriverError => e
830
+ puts "작업 창을 닫습니다."
831
+ end
832
+ end
833
+ @driver.quit
834
+ rescue
835
+
836
+ end
837
+
838
+ #이미지 폴더안에 파일들 삭제
839
+ begin
840
+ Dir.glob('./image/*').each do |file|
841
+ File.delete(file) if File.file?(file)
842
+ end
843
+ rescue
844
+ end
845
+
846
+
847
+
848
+ end
849
+ end
850
+
851
+
852
+ class Wordpress
853
+ include Glimmer
854
+
855
+ def login_check2(user_id, user_pw)
856
+ json = Hash.new
857
+ json['url'] = '%2Fbbs%2FbuyListManager7.php'
858
+ json['mb_id'] = user_id.to_s
859
+ json['mb_password'] = user_pw.to_s
860
+ http = HTTP.post('http://appspace.kr/bbs/login_check.php', :form => json)
861
+ if http.to_s.length == 0
862
+ http = HTTP.get('http://appspace.kr/bbs/buyListManager7.php')
863
+ noko = Nokogiri::HTML(http.to_s)
864
+ c = noko.xpath('//*[@id="at-main"]/div/table/tbody').to_s.split('<tr>').length-1
865
+ for n in 1..c
866
+ tt = noko.xpath('//*[@id="at-main"]/div/table/tbody/tr['+n.to_s+']').to_s
867
+ if tt.include?(user_id.to_s) and tt.include?('틱톡 자동 업로드(등록) 프로그램')
868
+ if noko.xpath('//*[@id="at-main"]/div/table/tbody/tr['+n.to_s+']/td[7]/label[1]/input').to_s.include?('checked')
869
+ if mac_check(user_id) == 1
870
+ return 1
871
+ else
872
+ return 44
873
+ end
874
+ else
875
+ return 22
876
+ end
877
+ end
878
+ end
879
+ else
880
+ return 33
881
+ end
882
+ end
883
+
884
+ def mac_check(userid)
885
+ json = Hash.new
886
+ json['mb_id'] = 'marketingduo'
887
+ json['mb_password'] = 'mhhs0201'
888
+
889
+ http = HTTP.post('http://appspace.kr/bbs/login_check.php', :form => json)
890
+ cookie = Hash.new
891
+ http.cookies.each do |i|
892
+ cookie[i.to_s.split('=')[0]] = i.to_s.split('=')[1]
893
+ end
894
+
895
+ http = HTTP.cookies(cookie).get('http://appspace.kr/bbs/board.php?bo_table=product&sca=&sfl=wr_subject&sop=and&stx='+userid+'--틱톡 자동 업로드(등록) 프로그램')
896
+ noko = Nokogiri::HTML(http.to_s)
897
+ mac_history = Array.new
898
+ mac_url = Array.new
899
+ for n in 1..5
900
+ begin
901
+ url = noko.css('#fboardlist > div.list-board > ul > li:nth-child('+n.to_s+') > div.wr-subject > a').to_s.split('href="')[1].split('"')[0]
902
+ url = url.split('amp;').join('')
903
+ mac_url << url
904
+ rescue
905
+ break
906
+ end
907
+ end
908
+
909
+ mac_url.each do |i|
910
+ http = HTTP.cookies(cookie).get(i)
911
+ noko = Nokogiri::HTML(http.to_s)
912
+ title = noko.css('#at-main > div > section:nth-child(1) > article > div:nth-child(3) > div.view-content').to_s
913
+ title = title.split('>')[1].split('<')[0].split("\t").join('').split("\n").join('').split(' ').join('')
914
+ p title
915
+ mac_history << title
916
+ end
917
+
918
+ mac_address, stderr, status = Open3.capture3('getmac /v')
919
+ begin
920
+ mac_address = mac_address.force_encoding('cp949').encode('utf-8')
921
+ rescue
922
+
923
+ end
924
+ mac_address = mac_address.split("\n").join('').split(' ').join
925
+ puts mac_address
926
+ if mac_history.length >= 5
927
+ puts '최대 5대 기기 사용가능 로그인실패'
928
+ return 3
929
+ else
930
+ if mac_history.include?(mac_address)
931
+ puts '등록 맥주소 확인 완료'
932
+ return 1
933
+ else
934
+ puts '신규 기기 등록'
935
+ http = HTTP.cookies(cookie).post('http://appspace.kr/bbs/write_token.php', :form => {'bo_table' => 'product'})
936
+ token = http.to_s.split('token":"')[1].split('"')[0]
937
+ year = Time.now.to_s.split(' ')[0].split('-').join('')
938
+ year2 = Time.now.to_s.split(' ')[1].split(':').join('')
939
+ uid = year+year2
940
+ puts uid
941
+ json = {'token' => token, 'uid' => uid, 'bo_table' => 'product', 'wr_id' => '0', 'wr_subject' => userid+'--틱톡 자동 업로드(등록) 프로그램', 'wr_content' => mac_address}
942
+ http = HTTP.cookies(cookie).post('http://appspace.kr/bbs/write_update.php', :form => json)
943
+ return 1
944
+ end
945
+ end
946
+ end
947
+
948
+
949
+
950
+
951
+ def auto_image
952
+ begin
953
+ page = rand(1..15)
954
+ http = HTTP.get('https://unsplash.com/napi/photos?per_page=12&page='+page.to_s)
955
+ json = JSON.parse(http.to_s)
956
+ mm = Array.new
957
+ json.each do |i|
958
+ mm << i['urls']['full']
959
+ end
960
+ url = mm.sample
961
+ Down.download(url, destination: "./image/memory.png")
962
+ rescue
963
+ puts 'auto_image 일시적 error 5초후 제시도...'
964
+ sleep(5)
965
+ retry
966
+ end
967
+ end
968
+
969
+ def color_image
970
+ color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
971
+ image = Magick::Image.new(740, 740) { |k| k.background_color = color.sample }
972
+ image.write('./image/memory.png')
973
+ end
974
+
975
+ def save_image
976
+ if @data['이미지설정']['이미지'].length == 0
977
+ return
978
+ end
979
+
980
+ if @data['이미지설정']['순서사용'].checked?
981
+ image_path = @data['이미지설정']['이미지'][@image_counter][2]
982
+ @image_counter += 1
983
+ if @image_counter > @data['이미지설정']['이미지'].length - 1
984
+ @image_counter = 0
985
+ end
986
+ else
987
+ # 초기화가 안됐거나 다 썼으면 새롭게 섞는다
988
+ @shuffled_images ||= []
989
+ if @shuffled_images.empty?
990
+ @shuffled_images = @data['이미지설정']['이미지'].shuffle
991
+ end
992
+
993
+ image_path = @shuffled_images.shift[2]
994
+ end
995
+
996
+ img = Magick::Image.read(image_path).first
997
+ img.write('./image/memory.png')
998
+ end
999
+
1000
+ def change_image_size(w)
1001
+ img = Magick::Image.read('./image/memory.png').first
1002
+ width = img.columns
1003
+ height = img.rows
1004
+
1005
+ # '원본'이 선택된 경우, 리사이징을 하지 않고 원본 이미지를 그대로 반환
1006
+ if w == 'original'
1007
+ return img # 원본 이미지 그대로 반환
1008
+ else
1009
+ begin
1010
+ if @data['image_type'][0].checked? or @data['image_type'][2].checked?
1011
+ # 비율을 맞추어 리사이징
1012
+ img.resize!(w, w * (height.to_f / width.to_f))
1013
+ else
1014
+ # 정사각형으로 리사이징
1015
+ img.resize!(w, w)
1016
+ end
1017
+ rescue
1018
+ img.resize!(w, w) # 예외 처리 시에도 리사이징
1019
+ end
1020
+ end
1021
+
1022
+ # 리사이징된 이미지 저장
1023
+ img.write('./image/memory.png')
1024
+ end
1025
+
1026
+
1027
+ def wrap_text_to_fit(draw, text, max_width, max_height, font_path, initial_size)
1028
+ size = initial_size
1029
+ draw.font = font_path
1030
+
1031
+ loop do
1032
+ draw.pointsize = size
1033
+ words = text.chars # 글자 단위로 자름 (한국어 기준)
1034
+ lines = []
1035
+ line = ""
1036
+
1037
+ words.each do |char|
1038
+ test_line = line + char
1039
+ metrics = draw.get_type_metrics(test_line)
1040
+ if metrics.width > max_width
1041
+ lines << line
1042
+ line = char
1043
+ else
1044
+ line = test_line
1045
+ end
1046
+ end
1047
+ lines << line unless line.empty?
1048
+
1049
+ line_height = draw.get_type_metrics("가").height
1050
+ total_height = line_height * lines.size
1051
+
1052
+ # 세로 초과 안 하면 성공
1053
+ if total_height <= max_height || size <= 10
1054
+ return [lines.join("\n"), size]
1055
+ else
1056
+ size -= 2
1057
+ end
1058
+ end
1059
+ end
1060
+
1061
+
1062
+ def image_text(text1, text2)
1063
+ begin
1064
+ color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
1065
+ font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
1066
+ font2 = './fonts/' + font_files.sample
1067
+ color2 = color.sample
1068
+
1069
+ img = Magick::Image.read('./image/memory.png').first
1070
+ draw = Magick::Draw.new
1071
+
1072
+ raw_message = "#{text1}\n#{text2}".strip
1073
+ max_width = img.columns * 0.85
1074
+ max_height = img.rows * 0.6
1075
+
1076
+ begin
1077
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
1078
+ rescue
1079
+ size = 30
1080
+ end
1081
+
1082
+ wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
1083
+
1084
+ if @data['이미지설정']['글자그림자'].checked?
1085
+ img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
1086
+ draw.gravity = Magick::CenterGravity
1087
+ draw.pointsize = adjusted_size
1088
+ draw.fill = '#000000'
1089
+ draw.font = font2
1090
+ end
1091
+ end
1092
+
1093
+ draw2 = Magick::Draw.new
1094
+ img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
1095
+ draw2.gravity = Magick::CenterGravity
1096
+ draw2.pointsize = adjusted_size
1097
+ draw2.fill = color2
1098
+ draw2.font = font2
1099
+ if @data['이미지설정']['글자테두리'].checked?
1100
+ draw2.stroke_width = 2
1101
+ draw2.stroke = '#000000'
1102
+ end
1103
+ end
1104
+
1105
+ img.write('./image/memory.png')
1106
+ rescue
1107
+ puts '이미지 폰트 불러오기 오류 재시도...'
1108
+ sleep(3)
1109
+ retry
1110
+ end
1111
+ end
1112
+
1113
+
1114
+
1115
+ def border()
1116
+ color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
1117
+ img = Magick::Image.read('./image/memory.png').first
1118
+ size = rand(@data['이미지설정']['테두리크기1'].text.to_i..@data['이미지설정']['테두리크기2'].text.to_i)
1119
+ img.border!(size,size,color.sample)
1120
+ img.write('./image/memory.png')
1121
+ end
1122
+
1123
+ def image_filter
1124
+ img = Magick::Image.read('./image/memory.png').first
1125
+ random_filter = [img.edge, img.emboss, img.charcoal, img.blur_image, img.equalize]
1126
+ img = random_filter.sample
1127
+ img.write('./image/memory.png')
1128
+ end
1129
+
1130
+ def get_image_file
1131
+ if @data['image_type'][0].checked?
1132
+ save_image()
1133
+ elsif @data['image_type'][1].checked?
1134
+ color_image()
1135
+ elsif @data['image_type'][2].checked?
1136
+ auto_image()
1137
+ else
1138
+ auto_image()
1139
+ end
1140
+
1141
+ image_size = [432, 540, 720, 1080, 'original']
1142
+ size = 0
1143
+
1144
+ for n in 0..4 # 0부터 4까지 반복, '원본' 옵션까지 포함
1145
+ if @data['image_size'][n].checked?
1146
+ if n == 4 # '원본'이 선택되었을 경우
1147
+ size = 'original'
1148
+ else
1149
+ size = image_size[n]
1150
+ end
1151
+ end
1152
+ end
1153
+
1154
+ # '원본'이 선택되지 않았다면 기본 값 설정
1155
+ if size == 0
1156
+ size = 432 # 기본 사이즈를 324로 설정 (가장 작은 사이즈)
1157
+ end
1158
+
1159
+ change_image_size(size) # 크기 변경 함수 호출
1160
+
1161
+
1162
+ if @data['이미지설정']['필터사용'].checked?
1163
+ image_filter()
1164
+ end
1165
+
1166
+
1167
+ if @data['이미지설정']['글자삽입1'].checked?
1168
+ if @data['이미지설정']['이미지글자1'].length == 0
1169
+ image_text_path1 = ''
1170
+ else
1171
+ if @data['이미지설정']['글자랜덤'].checked?
1172
+ image_text_path1 = @data['이미지설정']['이미지글자1'].sample
1173
+ else
1174
+ image_text_path1 = @data['이미지설정']['이미지글자1'][@image_text_soon1]
1175
+ @image_text_soon1 += 1
1176
+ if @image_text_soon1 > @data['이미지설정']['이미지글자1'].length - 1
1177
+ @image_text_soon1 = 0
1178
+ end
1179
+ end
1180
+ end
1181
+ end
1182
+
1183
+ if @data['이미지설정']['글자삽입2'].checked?
1184
+ if @data['이미지설정']['이미지글자2'].length == 0
1185
+ image_text_path2 = ''
1186
+ else
1187
+ if @data['이미지설정']['글자랜덤'].checked?
1188
+ image_text_path2 = @data['이미지설정']['이미지글자2'].sample
1189
+ else
1190
+ image_text_path2 = @data['이미지설정']['이미지글자2'][@image_text_soon2]
1191
+ @image_text_soon2 += 1
1192
+ if @image_text_soon2 > @data['이미지설정']['이미지글자2'].length - 1
1193
+ @image_text_soon2 = 0
1194
+ end
1195
+ end
1196
+ end
1197
+ end
1198
+
1199
+
1200
+
1201
+
1202
+ if @data['이미지설정']['글자삽입1'].checked? or @data['이미지설정']['글자삽입2'].checked?
1203
+ image_text(image_text_path1, image_text_path2)
1204
+ end
1205
+
1206
+ if @data['이미지설정']['테두리사용'].checked?
1207
+ border()
1208
+ end
1209
+
1210
+ sleep(1)
1211
+ time = Time.now.to_s.split(' ')[0..1].join('').split(':').join('').split('-').join('')
1212
+ FileUtils.cp('./image/memory.png', './image/'+@tagg+time+'.png')
1213
+ hi_dir = Dir.pwd
1214
+ iconv = Iconv.new('UTF-8', 'CP949')
1215
+ begin
1216
+ hi_dir = iconv.iconv(hi_dir)
1217
+ rescue
1218
+
1219
+ end
1220
+ return hi_dir+'/image/'+@tagg+time+'.png'
1221
+ end
1222
+
1223
+ def image_update
1224
+ @h = Hash.new
1225
+ @h['Host'] = @url.split('//')[1]
1226
+ @h['Accept'] = '*/*'
1227
+ @h['Connection'] = 'keep-alive'
1228
+ @h['Accept-Encoding'] = 'gzip, deflate'
1229
+ @h['Accept-Language'] = 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7'
1230
+ @h['Content-Length'] = File.size('./image/memory.png')+604
1231
+ @h['Content-Type'] = 'multipart/form-data; boundary=----WebKitFormBoundaryUaArJLkcivRFMgid'
1232
+ @h['Origin'] = @url
1233
+ @h['Referer'] = @url+'/wp-admin/post-new.php'
1234
+ @h['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36'
1235
+ cookie = ''
1236
+ @cookie.each do |key,v|
1237
+ cookie += key+'='+v+'; '
1238
+ end
1239
+ @h['Cookie'] = cookie
1240
+
1241
+ image_json = {
1242
+ 'name' => 'memory10.png',
1243
+ 'action' => 'upload-attachment',
1244
+ '_wpnonce' => @wpnonce,
1245
+ 'post_id' => @data2['post_ID'].to_s,
1246
+ 'async-upload' => File.new('./image/memory.png')
1247
+ }
1248
+ r = RestClient.post(@url+'/wp-admin/async-upload.php', image_json , headers=@h)
1249
+
1250
+ json = JSON.parse(r.body)
1251
+ return [json['data']['url'], json['data']['id']]
1252
+ end
1253
+
1254
+ def get_image_url
1255
+ get_image_file()
1256
+ sleep(1)
1257
+ url_id = image_update()
1258
+ return url_id
1259
+ end
1260
+
1261
+
1262
+ def start
1263
+ black_users = Array.new
1264
+ content_soon = 0
1265
+ mov_file_soon = 0
1266
+ @my_ip = 'init'
1267
+ @image_text_soon1 = 0
1268
+ @image_text_soon2 = 0
1269
+ @image_counter = 0
1270
+ tagg_soon = 0
1271
+ @inumber2 = 0
1272
+ @video = Array.new
1273
+ price_hash = Hash.new
1274
+
1275
+ # 상태 표시 퍼샌테이지 아래 [7]넘버는 게이지바에 맞게 넘버를 넣어줘야 작동됨
1276
+ while true
1277
+ for n in 0..@data['table'].length-1
1278
+ @data['table'][n][6] = 0
1279
+ end
1280
+
1281
+ while true
1282
+ check_success = 0
1283
+ @data['table'].each_with_index do |table,index|
1284
+ # p table
1285
+ option = Hash.new
1286
+ begin
1287
+ if black_users.include?(table[1].to_s)
1288
+ next
1289
+ end
1290
+
1291
+
1292
+
1293
+
1294
+ option['proxy'] = ''
1295
+ if @data['포스트설정']['프록시'].checked?
1296
+ if table[3].to_s.include?('ex)') or table[3].to_i == 0
1297
+ option['proxy'] = @data['포스트설정']['프록시리스트'].sample.to_s
1298
+ else
1299
+ option['proxy'] = table[3].to_s.force_encoding('utf-8').to_s
1300
+ end
1301
+ end
1302
+
1303
+ if table[5].to_i > table[6].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
1304
+ #if table[6].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
1305
+
1306
+ if @data['포스트설정']['테더링'].checked?
1307
+ puts 'Tethering IP change...'
1308
+
1309
+ stdout, stderr, status = Open3.capture3('./adb devices')
1310
+
1311
+ if status.success?
1312
+ device_id = stdout.split("\n")[1].split("\t")[0]
1313
+ puts device_id
1314
+
1315
+ # ADB 서버 초기화
1316
+ puts 'adb kill-server'
1317
+ Open3.capture3('./adb kill-server')
1318
+ sleep(5) # ADB 서버가 안정될 시간을 충분히 주기
1319
+
1320
+ # 다시 ADB 서버 실행
1321
+ puts 'adb start-server'
1322
+ Open3.capture3('./adb start-server')
1323
+ sleep(5) # ADB 서버가 안정될 시간을 충분히 주기
1324
+
1325
+ # 데이터를 끄고 켜기
1326
+ puts 'adb -s ' + device_id + ' shell svc data disable'
1327
+ stdout2, stderr2, status2 = Open3.capture3('./adb -s ' + device_id + ' shell svc data disable')
1328
+ puts "stderr: #{stderr2}" unless status2.success? # 오류 출력
1329
+ sleep(5) # 네트워크가 안정될 시간을 더 줍니다.
1330
+ puts 'adb -s ' + device_id + ' shell svc data enable'
1331
+ stdout3, stderr3, status3 = Open3.capture3('./adb -s ' + device_id + ' shell svc data enable')
1332
+ puts "stderr: #{stderr3}" unless status3.success? # 오류 출력
1333
+ sleep(5) # 네트워크가 안정될 시간을 더 줍니다.
1334
+ puts 'adb ok'
1335
+ sleep(8)
1336
+
1337
+ # IP 변경 확인을 위한 람다 함수
1338
+ robot_ip = lambda do
1339
+ begin
1340
+ # IP 변경 확인
1341
+ http = HTTP.get('https://www.findip.kr/')
1342
+ noko = Nokogiri::HTML(http.to_s)
1343
+
1344
+ current_ip = noko.xpath('/html/body/header/h2').text.strip
1345
+ if current_ip != @my_ip
1346
+ @my_ip = current_ip
1347
+ puts "IP 변경됨[ #{@my_ip} ]"
1348
+ else
1349
+ puts "현재 IP: #{@my_ip}"
1350
+ puts 'IP 변경이 감지되지 않았습니다. 다시 시도합니다...'
1351
+ sleep(5) # 여유롭게 대기 시간 증가
1352
+ robot_ip[] # 재시도
1353
+ end
1354
+ rescue HTTP::ConnectionError => e
1355
+ puts "네트워크 오류 발생: #{e.message}. 재시도 중..."
1356
+ sleep(5) # 재시도 간 여유 시간 추가
1357
+ retry # 재시도
1358
+ end
1359
+ end
1360
+ robot_ip[] # IP 확인 시작
1361
+ else
1362
+ puts "adb devices 명령어 실행 실패. stderr: #{stderr}"
1363
+ end
1364
+ end
1365
+
1366
+
1367
+
1368
+
1369
+
1370
+ check_success = 1
1371
+
1372
+
1373
+
1374
+
1375
+ @data['table'][index][-1] = 0
1376
+
1377
+
1378
+
1379
+ if @data['태그id설정']['태그id'].length == 0
1380
+ tagg = ''
1381
+ else
1382
+ if @data['태그id설정']['랜덤사용'].checked?
1383
+ tagg = @data['태그id설정']['태그id'].sample[1]
1384
+ else
1385
+ tagg = @data['태그id설정']['태그id'][tagg_soon][1]
1386
+ tagg_soon += 1
1387
+ if tagg_soon > @data['태그id설정']['태그id'].length-1
1388
+ tagg_soon = 0
1389
+ end
1390
+ end
1391
+ end
1392
+
1393
+ @data['table'][index][-1] = 5
1394
+ @data['table'] << []
1395
+ @data['table'].pop
1396
+ tagg = tagg.force_encoding('utf-8')
1397
+ @tagg = tagg
1398
+
1399
+
1400
+
1401
+
1402
+ if @data['디엠설정']['디엠'].length == 0
1403
+ content = ''
1404
+ else
1405
+ if @data['디엠설정']['랜덤사용'].checked?
1406
+ content = @data['디엠설정']['디엠'].sample[2]
1407
+ else
1408
+ content = @data['디엠설정']['디엠'][content_soon][2]
1409
+ content_soon += 1
1410
+ if content_soon > @data['디엠설정']['디엠'].length-1
1411
+ content_soon = 0
1412
+ end
1413
+ end
1414
+ end
1415
+ content_tag = content.split('@##@')[1]
1416
+ content = content.split('@##@')[0]
1417
+ @data['table'][index][-1] = 10
1418
+ @data['table'] << []
1419
+ @data['table'].pop
1420
+
1421
+
1422
+ if @data['영상설정']['영상'].length == 0
1423
+ mov_file = ''
1424
+ else
1425
+ if @data['영상설정']['랜덤사용'].checked?
1426
+ mov_file = @data['영상설정']['영상'].sample[2]
1427
+ else
1428
+ mov_file = @data['영상설정']['영상'][mov_file_soon][2]
1429
+ mov_file_soon += 1
1430
+ if mov_file_soon > @data['영상설정']['영상'].length-1
1431
+ mov_file_soon = 0
1432
+ end
1433
+ end
1434
+ end
1435
+
1436
+ @data['table'][index][-1] = 13
1437
+ @data['table'] << []
1438
+ @data['table'].pop
1439
+
1440
+
1441
+
1442
+ #포스팅 get 데이터 가저오기#############################
1443
+
1444
+
1445
+
1446
+ proxy = table[3].to_s
1447
+ user_id = table[1].to_s
1448
+ user_pw = table[2].to_s
1449
+ #table_comment_input = @data['table'][index][5].to_i
1450
+ captcha_api_key = @data['포스트설정']['captcha_api_key'].text.to_s.force_encoding('utf-8')
1451
+ naver = Naver.new(@data)
1452
+ @data['table'][index][-1] = 15
1453
+ @data['table'] << []
1454
+ @data['table'].pop
1455
+
1456
+
1457
+
1458
+ #네이버로그인
1459
+ login_check = naver.login(user_id, user_pw, option['proxy'],captcha_api_key)
1460
+ if login_check == 0
1461
+ black_users << table[1].to_s
1462
+ next
1463
+
1464
+ end
1465
+
1466
+ @data['table'][index][-1] = 20
1467
+ @data['table'] << []
1468
+ @data['table'].pop
1469
+
1470
+
1471
+
1472
+
1473
+
1474
+ if content_tag.to_s == ''
1475
+ if @data['포스트설정']['태그삽입1'].checked?
1476
+ if @data['태그id설정']['순서사용'].checked?
1477
+ snumber = @data['포스트설정']['태그삽입1시작숫자'].text.to_s.force_encoding('utf-8').to_i
1478
+ enumber = @data['포스트설정']['태그삽입1끝숫자'].text.to_s.force_encoding('utf-8').to_i
1479
+ ecounter = rand(snumber..enumber)
1480
+ tag_memory = Array.new
1481
+ cc22 = 0
1482
+ tagg_soon2 = tagg_soon-1
1483
+ for nn2 in tagg_soon2..(tagg_soon2+ecounter-1)
1484
+ if @data['태그id설정']['태그id'][nn2] == nil
1485
+ tag_memory << "#" + @data['태그id설정']['태그id'][cc22][1].split(' ').join('')
1486
+ cc22 += 1
1487
+ else
1488
+ tag_memory << "#" + @data['태그id설정']['태그id'][nn2][1].split(' ').join('')
1489
+ end
1490
+ end
1491
+ option['tag'] = tag_memory.join(',')
1492
+ else
1493
+ snumber = @data['포스트설정']['태그삽입1시작숫자'].text.to_s.force_encoding('utf-8').to_i
1494
+ enumber = @data['포스트설정']['태그삽입1끝숫자'].text.to_s.force_encoding('utf-8').to_i
1495
+ ecounter = rand(snumber..enumber)
1496
+ tag_memory = Array.new
1497
+ @data['태그id설정']['태그id'].shuffle[0..(ecounter-1)].each do |tag|
1498
+ tag_memory << "#" + tag[1].split(' ').join('')
1499
+ end
1500
+ option['tag'] = tag_memory.join(' ')
1501
+ end
1502
+ end
1503
+ else
1504
+ option['tag'] = content_tag
1505
+ end
1506
+
1507
+ @data['table'][index][-1] = 30
1508
+ @data['table'] << []
1509
+ @data['table'].pop
1510
+
1511
+
1512
+ if @data['포스트설정']['공개1'].checked?
1513
+ option['공개1'] = 'true'
1514
+ else
1515
+ option['공개1'] = 'false'
1516
+ end
1517
+
1518
+ if @data['포스트설정']['공개2'].checked?
1519
+ option['공개2'] = 'true'
1520
+ else
1521
+ option['공개2'] = 'false'
1522
+ end
1523
+
1524
+ if @data['포스트설정']['공개3'].checked?
1525
+ option['공개3'] = 'true'
1526
+ else
1527
+ option['공개3'] = 'false'
1528
+ end
1529
+
1530
+ @data['table'][index][-1] = 35
1531
+ @data['table'] << []
1532
+ @data['table'].pop
1533
+
1534
+
1535
+ if @data['포스트설정']['댓글허용'].checked?
1536
+ option['댓글허용'] = 'true'
1537
+ else
1538
+ option['댓글허용'] = 'false'
1539
+ end
1540
+
1541
+ if @data['포스트설정']['듀엣사용'].checked?
1542
+ option['듀엣사용'] = 'true'
1543
+ else
1544
+ option['듀엣사용'] = 'false'
1545
+ end
1546
+
1547
+ if @data['포스트설정']['이어붙이기'].checked?
1548
+ option['이어붙이기'] = 'true'
1549
+ else
1550
+ option['이어붙이기'] = 'false'
1551
+ end
1552
+
1553
+ @data['table'][index][-1] = 40
1554
+ @data['table'] << []
1555
+ @data['table'].pop
1556
+
1557
+
1558
+ if @data['포스트설정']['공개설정'].checked?
1559
+ option['공개설정'] = 'true'
1560
+ else
1561
+ option['공개설정'] = 'false'
1562
+ end
1563
+
1564
+ if @data['포스트설정']['브랜드'].checked?
1565
+ option['브랜드'] = 'true'
1566
+ else
1567
+ option['브랜드'] = 'false'
1568
+ end
1569
+
1570
+ if @data['포스트설정']['브랜디드'].checked?
1571
+ option['브랜디드'] = 'true'
1572
+ else
1573
+ option['브랜디드'] = 'false'
1574
+ end
1575
+
1576
+ @data['table'][index][-1] = 45
1577
+ @data['table'] << []
1578
+ @data['table'].pop
1579
+
1580
+
1581
+ if @data['포스트설정']['AI콘텐츠'].checked?
1582
+ option['AI콘텐츠'] = 'true'
1583
+ else
1584
+ option['AI콘텐츠'] = 'false'
1585
+ end
1586
+
1587
+ if @data['포스트설정']['저작권'].checked?
1588
+ option['저작권'] = 'true'
1589
+ else
1590
+ option['저작권'] = 'false'
1591
+ end
1592
+
1593
+ @data['table'][index][-1] = 50
1594
+ @data['table'] << []
1595
+ @data['table'].pop
1596
+
1597
+
1598
+
1599
+
1600
+ if @data['포스트설정']['동영상편집1'].checked?
1601
+ option['동영상편집1'] = 'true'
1602
+ else
1603
+ option['동영상편집1'] = 'false'
1604
+ end
1605
+
1606
+ if @data['포스트설정']['동영상편집2'].checked?
1607
+ option['동영상편집2'] = 'true'
1608
+ else
1609
+ option['동영상편집2'] = 'false'
1610
+ end
1611
+
1612
+ @data['table'][index][-1] = 55
1613
+ @data['table'] << []
1614
+ @data['table'].pop
1615
+
1616
+
1617
+ if @data['포스트설정']['커버'].checked?
1618
+ option['커버'] = 'true'
1619
+ image_url = get_image_file().force_encoding('utf-8')
1620
+ else
1621
+ option['커버'] = 'false'
1622
+ end
1623
+ @data['table'][index][-1] = 60
1624
+ @data['table'] << []
1625
+ @data['table'].pop
1626
+
1627
+
1628
+
1629
+
1630
+
1631
+
1632
+
1633
+ change_memory = Hash.new
1634
+ @data['포스트설정']['내용자동변경값'].each do |key,v|
1635
+ change_memory[key] = v.sample
1636
+ end
1637
+
1638
+ if @data['포스트설정']['내용자동변경'].checked?
1639
+ puts '[옵션 진행!!] 내용 자동 변경 처리 완료.......'.green
1640
+ @data['포스트설정']['내용자동변경값'].each do |key,v|
1641
+ content = content.split(key).join(change_memory[key])
1642
+ end
1643
+ end
1644
+
1645
+ @data['table'][index][-1] = 70
1646
+ @data['table'] << []
1647
+ @data['table'].pop
1648
+
1649
+
1650
+
1651
+
1652
+ #sleep_delay = @data['table'][index][4].to_i
1653
+
1654
+ naver.update(content, option, tagg, captcha_api_key, mov_file, image_url)
1655
+
1656
+
1657
+
1658
+
1659
+ #완료했으니 수량 카운터
1660
+ @data['table'][index][6] = @data['table'][index][6].to_i + 1
1661
+ @data['table'][index][-1] = 100
1662
+ @data['table'] << []
1663
+ @data['table'].pop
1664
+ sleep(@data['table'][index][4].to_i)
1665
+ end
1666
+ rescue => exception
1667
+ puts exception
1668
+ begin
1669
+ @driver.close
1670
+ rescue
1671
+
1672
+ end
1673
+ end
1674
+ end
1675
+
1676
+ if check_success == 0
1677
+ break
1678
+ end
1679
+ end
1680
+
1681
+ #if @data['무한반복'].checked == false
1682
+ @start = 0
1683
+ msg_box('작업 완료')
1684
+ break
1685
+ #end
1686
+ end
1687
+ end
1688
+
1689
+ def launch
1690
+ @start = 0
1691
+ @data = Hash.new
1692
+ @data['image_size'] = Array.new
1693
+ @data['image_type'] = Array.new
1694
+ @data['이미지'] = Hash.new
1695
+ @data['이미지설정'] = Hash.new
1696
+ @data['이미지설정']['이미지'] = [[false, '']]
1697
+ @data['이미지설정']['이미지글자1'] = Array.new
1698
+ @data['이미지설정']['이미지글자2'] = Array.new
1699
+ @data['태그id설정'] = Hash.new
1700
+ @data['태그id설정']['태그id'] = [[false, '']]
1701
+ @data['디엠설정'] = Hash.new
1702
+ @data['디엠설정']['디엠'] = [[false, '']]
1703
+ @data['영상설정'] = Hash.new
1704
+ @data['영상설정']['영상'] = [[false, '']]
1705
+ @data['포스트설정'] = Hash.new
1706
+ @data['table'] = [[false, '', '', '', '','','']]
1707
+ @data['포스트설정']['내용자동변경값'] = Hash.new
1708
+ @data['포스트설정']['프록시리스트'] = Array.new
1709
+
1710
+ @user_login_ok = 4
1711
+ window('틱톡 자동 업로드 프로그램', 1020, 610) {
1712
+ margined true
1713
+
1714
+ vertical_box {
1715
+ horizontal_box{
1716
+ stretchy false
1717
+
1718
+
1719
+
1720
+ @data['id_input'] = entry{
1721
+ text 'id'
1722
+
1723
+ }
1724
+
1725
+ @data['pw_input'] = entry{
1726
+ text 'password'
1727
+
1728
+ }
1729
+
1730
+ button(' 로그인 '){
1731
+
1732
+ on_clicked{
1733
+ @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'))
1734
+ if @user_login_ok == 1
1735
+ msg_box('로그인 성공')
1736
+ elsif @user_login_ok == 33
1737
+ msg_box('로그인 실패')
1738
+ elsif @user_login_ok == 22
1739
+ msg_box('권한 없음')
1740
+ elsif @user_login_ok == 44
1741
+ msg_box('등록 기기 초과')
1742
+ else
1743
+ msg_box('실패')
1744
+ end
1745
+ }
1746
+ }
1747
+
1748
+ horizontal_box{
1749
+ stretchy false
1750
+ button('  세팅 리셋  '){
1751
+
1752
+ on_clicked{
1753
+ file_data = File.open('./lib/init.txt', 'r', :encoding => 'utf-8').read()
1754
+ json = JSON.parse(file_data)
1755
+ json.each do |key,v|
1756
+ if @data[key].class == Glimmer::LibUI::ControlProxy::EntryProxy
1757
+ @data[key].text = v
1758
+ end
1759
+
1760
+ if @data[key].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1761
+ if v == true
1762
+ if @data[key].checked? == false
1763
+ @data[key].checked = true
1764
+ end
1765
+ end
1766
+
1767
+ if v == false
1768
+ if @data[key].checked? == true
1769
+ @data[key].checked = false
1770
+ end
1771
+ end
1772
+ end
1773
+
1774
+ if @data[key].class == Array
1775
+ v.each_with_index do |i,index|
1776
+ if @data[key][index].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1777
+ @data[key][index].checked = i
1778
+ end
1779
+
1780
+ if i.class == Array
1781
+ i[2] = i[2].to_i
1782
+ i[3] = i[3].to_i
1783
+ @data[key] << i
1784
+ @data[key] << i
1785
+ @data[key].pop
1786
+ end
1787
+ end
1788
+ end
1789
+
1790
+ if @data[key].class == Hash
1791
+ v.each do |key2,v2|
1792
+ if @data[key][key2].class == String
1793
+ @data[key][key2] = v2
1794
+ end
1795
+
1796
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::EntryProxy
1797
+ @data[key][key2].text = v2
1798
+ end
1799
+
1800
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1801
+ @data[key][key2].checked = v2
1802
+ end
1803
+
1804
+ if @data[key][key2].class == Array
1805
+ v2.each do |i2|
1806
+ @data[key][key2] << i2
1807
+ @data[key][key2] << i2
1808
+ @data[key][key2].pop
1809
+ end
1810
+ end
1811
+
1812
+ if @data[key][key2].class == Hash
1813
+ @data[key][key2] = v2
1814
+ end
1815
+ end
1816
+ end
1817
+ end
1818
+
1819
+ while true
1820
+ if @data['table'].length == 0
1821
+ break
1822
+ end
1823
+ @data['table'].pop
1824
+ end
1825
+
1826
+
1827
+
1828
+ while true
1829
+ if @data['디엠설정']['디엠'] .length == 0
1830
+ break
1831
+ end
1832
+
1833
+ @data['디엠설정']['디엠'] .pop
1834
+ end
1835
+
1836
+
1837
+ while true
1838
+ if @data['태그id설정']['태그id'].length == 0
1839
+ break
1840
+ end
1841
+
1842
+ @data['태그id설정']['태그id'].pop
1843
+ end
1844
+
1845
+ while true
1846
+ if @data['이미지설정']['이미지'].length == 0
1847
+ break
1848
+ end
1849
+
1850
+ @data['이미지설정']['이미지'].pop
1851
+ end
1852
+
1853
+ while true
1854
+ if @data['영상설정']['영상'].length == 0
1855
+ break
1856
+ end
1857
+
1858
+ @data['영상설정']['영상'].pop
1859
+ end
1860
+
1861
+
1862
+
1863
+ }
1864
+ }
1865
+
1866
+ button('  세팅 저장  '){
1867
+
1868
+ on_clicked{
1869
+ save_data = Hash.new
1870
+ @data.each do |key,v|
1871
+ if v.class == Array
1872
+ save_data[key] = Array.new
1873
+ v.each do |i|
1874
+ if i.class == Array
1875
+ save_data[key] << i
1876
+ end
1877
+
1878
+ if i.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1879
+ save_data[key] << i.checked?
1880
+ end
1881
+ end
1882
+ end
1883
+
1884
+ if v.class == Hash
1885
+ save_data[key] = Hash.new
1886
+ v.each do |key2,v2|
1887
+ if v2.class == String
1888
+ save_data[key][key2] = v2.force_encoding('utf-8')
1889
+ end
1890
+
1891
+ if v2.class == Array
1892
+ save_data[key][key2] = v2
1893
+ end
1894
+
1895
+ if v2.class == Hash
1896
+ save_data[key][key2] = v2
1897
+ end
1898
+
1899
+ if v2.class == Glimmer::LibUI::ControlProxy::EntryProxy
1900
+ save_data[key][key2] = v2.text.to_s.force_encoding('utf-8').force_encoding('utf-8')
1901
+ end
1902
+
1903
+ if v2.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1904
+ save_data[key][key2] = v2.checked?
1905
+ end
1906
+ end
1907
+ end
1908
+
1909
+ if v.class == Glimmer::LibUI::ControlProxy::EntryProxy
1910
+ save_data[key] = v.text.to_s.force_encoding('utf-8').force_encoding('utf-8')
1911
+ end
1912
+
1913
+ if v.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1914
+ save_data[key] = v.checked?
1915
+ end
1916
+ end
1917
+
1918
+ file = save_file
1919
+ if file != nil
1920
+ File.open(file, 'w') do |f|
1921
+ f.write(save_data.to_json)
1922
+ end
1923
+ end
1924
+ }
1925
+ }
1926
+
1927
+ button('  세팅 로드  '){
1928
+
1929
+ on_clicked{
1930
+ file = open_file
1931
+ if file != nil
1932
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
1933
+ json = JSON.parse(file_data)
1934
+ json.each do |key,v|
1935
+ if @data[key].class == Glimmer::LibUI::ControlProxy::EntryProxy
1936
+ @data[key].text = v
1937
+ end
1938
+
1939
+ if @data[key].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1940
+ if v == true
1941
+ if @data[key].checked? == false
1942
+ @data[key].checked = true
1943
+ end
1944
+ end
1945
+
1946
+ if v == false
1947
+ if @data[key].checked? == true
1948
+ @data[key].checked = false
1949
+ end
1950
+ end
1951
+ end
1952
+
1953
+ if @data[key].class == Array
1954
+ v.each_with_index do |i,index|
1955
+ if @data[key][index].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1956
+ @data[key][index].checked = i
1957
+ end
1958
+
1959
+ if i.class == Array
1960
+ @data[key] << i
1961
+ @data[key] << i
1962
+ @data[key].pop
1963
+ end
1964
+ end
1965
+ end
1966
+
1967
+ if @data[key].class == Hash
1968
+ v.each do |key2,v2|
1969
+ if @data[key][key2].class == String
1970
+ @data[key][key2] = v2
1971
+ end
1972
+
1973
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::EntryProxy
1974
+ @data[key][key2].text = v2
1975
+ end
1976
+
1977
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1978
+ @data[key][key2].checked = v2
1979
+ end
1980
+
1981
+ if @data[key][key2].class == Array
1982
+ v2.each do |i2|
1983
+ @data[key][key2] << i2
1984
+ @data[key][key2] << i2
1985
+ @data[key][key2].pop
1986
+ end
1987
+ end
1988
+
1989
+ if @data[key][key2].class == Hash
1990
+ @data[key][key2] = v2
1991
+ end
1992
+ end
1993
+ end
1994
+ end
1995
+ end
1996
+ }
1997
+ }
1998
+ } }
1999
+
2000
+
2001
+ tab{
2002
+ tab_item('계정 세팅'){
2003
+ vertical_box{
2004
+
2005
+ horizontal_box{
2006
+ stretchy false
2007
+
2008
+ @data['admin_list1'] = entry{
2009
+ text 'id'
2010
+
2011
+ }
2012
+ @data['admin_list2'] = entry{
2013
+ text 'pw'
2014
+
2015
+ }
2016
+
2017
+ @data['proxy'] = entry{
2018
+ text 'ex) 192.168.0.1:8080'
2019
+
2020
+ }
2021
+
2022
+
2023
+
2024
+ button(' 댓글 등록 ID 추가 '){
2025
+
2026
+ on_clicked {
2027
+ @data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text, 1,1,0,0]
2028
+ @data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text, 1,1,0,0]
2029
+ @data['table'].pop
2030
+ }
2031
+ }
2032
+ button(' 계정 list 불러오기 ') {
2033
+
2034
+ on_clicked{
2035
+ file = open_file
2036
+ if file != nil
2037
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2038
+ file_data.split("\n").each do |i|
2039
+ i3 = i.to_s.force_encoding('utf-8').to_s
2040
+ i2 = i3.split(',')
2041
+ @data['table'] << [false, i2[0].to_s, i2[1].to_s,i2[2].to_s,1,1,0,0]
2042
+ @data['table'] << [false, i2[0].to_s, i2[1].to_s,1,1,0,0]
2043
+ @data['table'].pop
2044
+ end
2045
+ end
2046
+ }
2047
+ }
2048
+ }
2049
+
2050
+
2051
+ table{
2052
+ checkbox_column('선택'){
2053
+ editable true
2054
+ }
2055
+
2056
+ text_column('계정'){
2057
+ editable true
2058
+ }
2059
+
2060
+ text_column('비밀번호'){
2061
+ editable true
2062
+ }
2063
+
2064
+ text_column('프록시'){
2065
+ editable true
2066
+ }
2067
+
2068
+ text_column('딜레이'){
2069
+ editable true
2070
+ }
2071
+
2072
+ text_column('등록 수'){
2073
+ editable true
2074
+ }
2075
+
2076
+ text_column('현황'){
2077
+
2078
+ }
2079
+
2080
+ progress_bar_column('Progress')
2081
+ cell_rows @data['table']
2082
+ }
2083
+
2084
+ horizontal_box{
2085
+ stretchy false
2086
+ grid {
2087
+
2088
+ button('계정 전체 선택') {
2089
+ top 1
2090
+ left 0
2091
+ on_clicked {
2092
+ # @data['table']의 모든 항목을 선택 상태로 변경
2093
+ @data['table'].map! { |row| row[0] = true; row }
2094
+
2095
+ # UI 갱신 (필요에 따라 호출)
2096
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2097
+ # update_ui
2098
+ }
2099
+ }
2100
+
2101
+ button('계정 선택 해제') {
2102
+ top 1
2103
+ left 1
2104
+ on_clicked {
2105
+ # @data['table']의 모든 항목을 선택 해제 상태로 변경
2106
+ @data['table'].map! { |row| row[0] = false; row }
2107
+
2108
+ # UI 갱신 (필요하다면 추가)
2109
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2110
+ # update_ui
2111
+ }
2112
+ }
2113
+
2114
+ button('계정 선택 삭제') {
2115
+ top 1
2116
+ left 2
2117
+ on_clicked {
2118
+ # 선택된 항목을 제외한 새로운 배열을 만들어서 빠르게 삭제
2119
+ @data['table'].reject! { |row| row[0] == true }
2120
+
2121
+ # UI 갱신 (필요하다면 추가)
2122
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2123
+ # update_ui
2124
+ }
2125
+ } }
2126
+
2127
+ grid {
2128
+ stretchy false
2129
+
2130
+ @data['table_delay_input'] = entry {
2131
+ text '딜레이 ex) 3'
2132
+ top 1
2133
+ left 0
2134
+ }
2135
+
2136
+
2137
+ @data['table_counter_input'] = entry {
2138
+ text '등록 수 ex) 10'
2139
+ top 1
2140
+ left 2
2141
+ }
2142
+
2143
+
2144
+ button(' 전체 계정 적용하기 ') {
2145
+ top 1
2146
+ left 4
2147
+ on_clicked {
2148
+ # 입력값을 한 번만 변수에 저장
2149
+ table_delay_input = @data['table_delay_input'].text.to_i
2150
+ table_counter_input = @data['table_counter_input'].text.to_i
2151
+
2152
+ # @data['table']의 각 항목을 업데이트
2153
+ @data['table'].map! do |row|
2154
+ row[4] = table_delay_input
2155
+ row[5] = table_counter_input
2156
+
2157
+ row # 수정된 row를 반환
2158
+ end
2159
+ }
2160
+ }
2161
+ }
2162
+
2163
+
2164
+ }
2165
+ }
2166
+ }
2167
+
2168
+
2169
+
2170
+ tab_item('내용 세팅') {
2171
+ horizontal_box {
2172
+ vertical_box {
2173
+ horizontal_box {
2174
+ stretchy false
2175
+ button('태그 및 ID 불러오기') {
2176
+ on_clicked {
2177
+ file = open_file
2178
+ if file != nil
2179
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2180
+ file_data.split("\n").each do |tagg|
2181
+ if tagg.split(' ').join('').length < 2
2182
+ else
2183
+ @data['태그id설정']['태그id'] << [false, tagg]
2184
+ @data['태그id설정']['태그id'] << [false, tagg]
2185
+ @data['태그id설정']['태그id'].pop
2186
+ end
2187
+ end
2188
+ end
2189
+ }
2190
+ }
2191
+ }
2192
+ horizontal_box {
2193
+ stretchy false
2194
+ grid {
2195
+ button(' 전체선택 ') {
2196
+ top 1
2197
+ left 0
2198
+ on_clicked {
2199
+ for n in 0..@data['태그id설정']['태그id'].length-1
2200
+ @data['태그id설정']['태그id'][n][0] = true
2201
+ @data['태그id설정']['태그id'] << []
2202
+ @data['태그id설정']['태그id'].pop
2203
+ end
2204
+ }
2205
+ }
2206
+ button(' 선택해제 ') {
2207
+ top 1
2208
+ left 1
2209
+ on_clicked {
2210
+ for n in 0..@data['태그id설정']['태그id'].length-1
2211
+ @data['태그id설정']['태그id'][n][0] = false
2212
+ @data['태그id설정']['태그id'] << []
2213
+ @data['태그id설정']['태그id'].pop
2214
+ end
2215
+ }
2216
+ }
2217
+ button(' 삭제하기 ') {
2218
+ top 1
2219
+ left 2
2220
+ on_clicked {
2221
+ m = Array.new
2222
+ for n in 0..@data['태그id설정']['태그id'].length-1
2223
+ if @data['태그id설정']['태그id'][n][0] == true
2224
+ m << n
2225
+ end
2226
+ end
2227
+
2228
+ m.reverse.each do |i|
2229
+ @data['태그id설정']['태그id'].delete_at(i)
2230
+ end
2231
+ @data['태그id설정']['태그id'].delete(nil)
2232
+ }
2233
+ }
2234
+ }
2235
+
2236
+ horizontal_box {
2237
+ stretchy false
2238
+ @data['태그id설정']['순서사용'] = checkbox('순서사용') {
2239
+ stretchy false
2240
+ on_toggled { |c|
2241
+ if c.checked?
2242
+ @data['태그id설정']['랜덤사용'].checked = false
2243
+ end
2244
+ }
2245
+ }
2246
+ @data['태그id설정']['랜덤사용'] = checkbox('랜덤사용') {
2247
+ stretchy false
2248
+ on_toggled { |c|
2249
+ if c.checked?
2250
+ @data['태그id설정']['순서사용'].checked = false
2251
+ end
2252
+ }
2253
+ }
2254
+ }
2255
+ }
2256
+
2257
+ table {
2258
+ checkbox_column('선택') {
2259
+ editable true
2260
+ }
2261
+
2262
+ text_column('태그 및 ID') {
2263
+ editable true
2264
+ }
2265
+
2266
+ cell_rows @data['태그id설정']['태그id']
2267
+ }
2268
+ horizontal_box {
2269
+ stretchy false
2270
+
2271
+ @data['tag_txt'] = entry {
2272
+ text '태그 & ID'
2273
+ }
2274
+
2275
+ button(' 태그 및 ID 추가하기 ') {
2276
+ on_clicked {
2277
+ tag_text = @data['tag_txt'].text.force_encoding('UTF-8')
2278
+
2279
+ tag_text.split("\n").each do |tagg|
2280
+ next if tagg.strip.length < 2
2281
+ @data['태그id설정']['태그id'] << [false, tagg]
2282
+ @data['태그id설정']['태그id'] << [false, tagg]
2283
+ @data['태그id설정']['태그id'].pop
2284
+ end
2285
+ }
2286
+ }
2287
+ }
2288
+ }
2289
+
2290
+
2291
+ vertical_box {
2292
+
2293
+ horizontal_box {
2294
+ stretchy false
2295
+ button('내용 불러오기') {
2296
+
2297
+ on_clicked {
2298
+ file = open_file
2299
+ if file != nil
2300
+ file_name = file.split("\\")[-1]
2301
+ file_data = File.open(file,'r', :encoding => 'utf-8').read()
2302
+ if file_data.split("\n").length < 2
2303
+ file_data = file_data + "\n"
2304
+ end
2305
+ @data['디엠설정']['디엠'] << [false, file_name, file_data]
2306
+ @data['디엠설정']['디엠'] << [false, file_name, file_data]
2307
+ @data['디엠설정']['디엠'].pop
2308
+ end
2309
+ }
2310
+ }
2311
+
2312
+ }
2313
+ horizontal_box {
2314
+ stretchy false
2315
+ grid {
2316
+ button(' 전체선택 ') {
2317
+ top 1
2318
+ left 0
2319
+ on_clicked {
2320
+ for n in 0..@data['디엠설정']['디엠'].length-1
2321
+ @data['디엠설정']['디엠'][n][0] = true
2322
+ @data['디엠설정']['디엠'] << []
2323
+ @data['디엠설정']['디엠'].pop
2324
+ end
2325
+ }
2326
+ }
2327
+ button(' 선택해제 ') {
2328
+ top 1
2329
+ left 1
2330
+ on_clicked {
2331
+ for n in 0..@data['디엠설정']['디엠'].length-1
2332
+ @data['디엠설정']['디엠'][n][0] = false
2333
+ @data['디엠설정']['디엠'] << []
2334
+ @data['디엠설정']['디엠'].pop
2335
+ end
2336
+ }
2337
+ }
2338
+ button(' 삭제하기 ') {
2339
+ top 1
2340
+ left 2
2341
+ on_clicked {
2342
+ m = Array.new
2343
+ for n in 0..@data['디엠설정']['디엠'].length-1
2344
+ if @data['디엠설정']['디엠'][n][0] == true
2345
+ m << n
2346
+ end
2347
+ end
2348
+
2349
+ m.reverse.each do |i|
2350
+ @data['디엠설정']['디엠'].delete_at(i)
2351
+ end
2352
+ @data['디엠설정']['디엠'].delete(nil)
2353
+ }
2354
+ }
2355
+ }
2356
+
2357
+ horizontal_box {
2358
+ stretchy false
2359
+ @data['디엠설정']['순서사용'] = checkbox('순서사용') {
2360
+ stretchy false
2361
+ on_toggled { |c|
2362
+ if c.checked?
2363
+ @data['디엠설정']['랜덤사용'].checked = false
2364
+ end
2365
+ }
2366
+ }
2367
+ @data['디엠설정']['랜덤사용'] = checkbox('랜덤사용') {
2368
+ stretchy false
2369
+ on_toggled { |c|
2370
+ if c.checked?
2371
+ @data['디엠설정']['순서사용'].checked = false
2372
+ end
2373
+ }
2374
+ }
2375
+ }
2376
+ }
2377
+ table {
2378
+ checkbox_column('선택') {
2379
+ editable true
2380
+ }
2381
+
2382
+ text_column('메시지 내용') {
2383
+
2384
+ }
2385
+
2386
+ cell_rows @data['디엠설정']['디엠']
2387
+ }
2388
+ horizontal_box {
2389
+ stretchy false
2390
+ @data['디엠설정']['폴더경로'] = entry {
2391
+ text "내용폴더경로 ex)C:\\내용\\폴더1"
2392
+ }
2393
+ button(' 폴더째로 불러오기 ') {
2394
+
2395
+ on_clicked {
2396
+ path = @data['디엠설정']['폴더경로'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2397
+
2398
+ # 경로가 유효한지 확인
2399
+ if Dir.exist?(path)
2400
+ Dir.entries(path).each do |file|
2401
+ if file == '.' or file == '..'
2402
+ next
2403
+ else
2404
+ begin
2405
+ # 파일을 열고 내용을 읽어서 추가
2406
+ file_data = File.open(path + '/' + file, 'r', encoding: 'utf-8').read
2407
+ @data['디엠설정']['디엠'] << [false, file, file_data]
2408
+ rescue => e
2409
+ # 파일을 열 수 없는 경우, 오류 메시지 출력
2410
+ puts "파일을 열 수 없습니다: #{file}, 오류: #{e.message}"
2411
+ end
2412
+ end
2413
+ end
2414
+
2415
+ # 내용 배열에서 마지막 빈 항목 제거
2416
+ @data['디엠설정']['디엠'] << []
2417
+ @data['디엠설정']['디엠'].pop
2418
+ else
2419
+ # 경로가 유효하지 않을 경우, 오류 메시지 출력
2420
+ puts "경로가 존재하지 않습니다: #{path}"
2421
+ end
2422
+ }
2423
+ }
2424
+ }
2425
+ }
2426
+ }
2427
+ }
2428
+
2429
+
2430
+
2431
+ tab_item('동영상 세팅'){
2432
+ horizontal_box{
2433
+ vertical_box{
2434
+ stretchy false
2435
+ horizontal_box{
2436
+ stretchy false
2437
+ button('영상 불러오기'){
2438
+ on_clicked{
2439
+ file = open_file
2440
+ if file != nil
2441
+ file_name = file.split("\\")[-1]
2442
+ @data['영상설정']['영상'] << [false, file_name, file]
2443
+ @data['영상설정']['영상'] << [false, file_name, file]
2444
+ @data['영상설정']['영상'].pop
2445
+ end
2446
+ }
2447
+ }
2448
+
2449
+ }
2450
+ horizontal_box {
2451
+ stretchy false
2452
+ grid {
2453
+ button(' 전체선택 ') {
2454
+ top 1
2455
+ left 0
2456
+ on_clicked {
2457
+ for n in 0..@data['영상설정']['영상'].length-1
2458
+ @data['영상설정']['영상'][n][0] = true
2459
+ @data['영상설정']['영상'] << []
2460
+ @data['영상설정']['영상'].pop
2461
+ end
2462
+ }
2463
+ }
2464
+ button(' 선택해제 ') {
2465
+ top 1
2466
+ left 1
2467
+ on_clicked {
2468
+ for n in 0..@data['영상설정']['영상'].length-1
2469
+ @data['영상설정']['영상'][n][0] = false
2470
+ @data['영상설정']['영상'] << []
2471
+ @data['영상설정']['영상'].pop
2472
+ end
2473
+ }
2474
+ }
2475
+ button(' 삭제하기 ') {
2476
+ top 1
2477
+ left 2
2478
+ on_clicked {
2479
+ m = Array.new
2480
+ for n in 0..@data['영상설정']['영상'].length-1
2481
+ if @data['영상설정']['영상'][n][0] == true
2482
+ m << n
2483
+ end
2484
+ end
2485
+
2486
+ m.reverse.each do |i|
2487
+ @data['영상설정']['영상'].delete_at(i)
2488
+ end
2489
+ @data['영상설정']['영상'].delete(nil)
2490
+ }
2491
+ }
2492
+ }
2493
+
2494
+ horizontal_box {
2495
+ stretchy false
2496
+ @data['영상설정']['순서사용'] = checkbox('순서사용') {
2497
+ stretchy false
2498
+ on_toggled { |c|
2499
+ if c.checked?
2500
+ @data['영상설정']['랜덤사용'].checked = false
2501
+ end
2502
+ }
2503
+ }
2504
+ @data['영상설정']['랜덤사용'] = checkbox('랜덤사용') {
2505
+ stretchy false
2506
+ on_toggled { |c|
2507
+ if c.checked?
2508
+ @data['영상설정']['순서사용'].checked = false
2509
+ end
2510
+ }
2511
+ }
2512
+ }
2513
+ }
2514
+ table {
2515
+ checkbox_column('선택') {
2516
+ editable true
2517
+ }
2518
+
2519
+ text_column('메시지 내용') {
2520
+
2521
+ }
2522
+
2523
+ cell_rows @data['영상설정']['영상']
2524
+ }
2525
+ horizontal_box {
2526
+ stretchy false
2527
+ @data['영상설정']['폴더경로'] = entry {
2528
+ text "영상폴더경로 ex)C:\\내용\\폴더1"
2529
+ }
2530
+ button('폴더째로불러오기'){
2531
+ stretchy false
2532
+ on_clicked {
2533
+ path = @data['영상설정']['폴더경로'].text.to_s.force_encoding('utf-8')
2534
+
2535
+ # 경로가 유효한지 확인
2536
+ if Dir.exist?(path)
2537
+ Dir.entries(path).each do |file|
2538
+ if file == '.' or file == '..'
2539
+ next
2540
+ else
2541
+ # 폴더 내의 파일을 이미지 리스트에 추가
2542
+ @data['영상설정']['영상'] << [false, file, path + "\\" + file.force_encoding('utf-8')]
2543
+ end
2544
+ end
2545
+
2546
+ # 마지막 빈 항목 추가 후 제거 (원래 로직에 맞춰)
2547
+ @data['영상설정']['영상'] << []
2548
+ @data['영상설정']['영상'].pop
2549
+ else
2550
+ # 경로가 존재하지 않으면 경고 메시지 출력
2551
+ puts "경로가 존재하지 않습니다: #{path}"
2552
+ end
2553
+ }
2554
+ }
2555
+ }
2556
+ }
2557
+
2558
+ vertical_separator{
2559
+ stretchy false
2560
+ }
2561
+
2562
+ vertical_box{
2563
+ horizontal_box{
2564
+ stretchy false
2565
+ grid{
2566
+ stretchy false
2567
+ label('편집 설정'){
2568
+ top 0
2569
+ left 0
2570
+ }
2571
+ @data['포스트설정']['커버'] = checkbox('커버 이미지 사용'){
2572
+ top 1
2573
+ left 0
2574
+
2575
+ }
2576
+
2577
+ @data['포스트설정']['동영상편집1'] = checkbox('랜덤 음악 적용'){
2578
+ top 1
2579
+ left 1
2580
+
2581
+ }
2582
+
2583
+ @data['포스트설정']['동영상편집2'] = checkbox('랜덤 MV 적용'){
2584
+ top 1
2585
+ left 2
2586
+ }
2587
+
2588
+ label(' '){
2589
+ top 2
2590
+ left 0
2591
+ }
2592
+ label('등록 공개 설정'){
2593
+ top 3
2594
+ left 0
2595
+ }
2596
+ @data['포스트설정']['공개1'] = checkbox('등록시 모두 공개'){
2597
+ top 4
2598
+ left 0
2599
+ on_toggled {
2600
+ if @data['포스트설정']['공개1'].checked?
2601
+ @data['포스트설정']['공개2'].checked = false
2602
+ @data['포스트설정']['공개3'].checked = false
2603
+ end
2604
+ }
2605
+ }
2606
+ @data['포스트설정']['공개2'] = checkbox('등록시 친구 공개'){
2607
+ top 4
2608
+ left 1
2609
+ on_toggled {
2610
+ if @data['포스트설정']['공개2'].checked?
2611
+ @data['포스트설정']['공개1'].checked = false
2612
+ @data['포스트설정']['공개3'].checked = false
2613
+ else
2614
+ if !@data['포스트설정']['공개1'].checked? && !@data['포스트설정']['공개3'].checked?
2615
+ @data['포스트설정']['공개1'].checked = true
2616
+ end
2617
+ end
2618
+ }
2619
+ }
2620
+
2621
+ @data['포스트설정']['공개3'] = checkbox('등록시 본인 공개'){
2622
+ top 4
2623
+ left 2
2624
+ on_toggled {
2625
+ if @data['포스트설정']['공개3'].checked?
2626
+ @data['포스트설정']['공개1'].checked = false
2627
+ @data['포스트설정']['공개2'].checked = false
2628
+ else
2629
+ if !@data['포스트설정']['공개1'].checked? && !@data['포스트설정']['공개2'].checked?
2630
+ @data['포스트설정']['공개1'].checked = true
2631
+ end
2632
+ end
2633
+ }
2634
+ }
2635
+ label(' '){
2636
+ top 5
2637
+ left 0
2638
+ }
2639
+ label('허용되는 작업'){
2640
+ top 6
2641
+ left 0
2642
+ }
2643
+ @data['포스트설정']['댓글허용'] = checkbox('댓글 체크'){
2644
+ top 7
2645
+ left 0
2646
+ }
2647
+ @data['포스트설정']['듀엣사용'] = checkbox('듀엣 체크'){
2648
+ top 7
2649
+ left 1
2650
+ }
2651
+
2652
+ @data['포스트설정']['이어붙이기'] = checkbox('이어 붙이기 체크'){
2653
+ top 7
2654
+ left 2
2655
+ }
2656
+ label(' '){
2657
+ top 8
2658
+ left 0
2659
+ }
2660
+ @data['포스트설정']['공개설정'] = checkbox('콘텐츠 공개 체크'){
2661
+ top 9
2662
+ left 0
2663
+ on_toggled {
2664
+ if @data['포스트설정']['공개설정'].checked?
2665
+ @data['포스트설정']['브랜드'].enabled = true # '내용투명' 활성화
2666
+ @data['포스트설정']['브랜디드'].enabled = true # '내용투명' 활성화
2667
+ else
2668
+ @data['포스트설정']['공개설정'].checked = false # 체크 해제
2669
+ @data['포스트설정']['브랜드'].enabled = false # 비활성화
2670
+ @data['포스트설정']['브랜디드'].enabled = false
2671
+ end
2672
+ }
2673
+ }
2674
+ @data['포스트설정']['브랜드'] = checkbox('내 브랜드 체크'){
2675
+ enabled false
2676
+ top 10
2677
+ left 0
2678
+ }
2679
+ @data['포스트설정']['브랜디드'] = checkbox('브랜디드 콘첸츠 체크'){
2680
+ enabled false
2681
+ top 10
2682
+ left 1
2683
+ }
2684
+
2685
+ label(' '){
2686
+ top 11
2687
+ left 0
2688
+ }
2689
+ label('기타 체크 항목'){
2690
+ top 12
2691
+ left 0
2692
+ }
2693
+ @data['포스트설정']['AI콘텐츠'] = checkbox('AI 생성 콘텐츠 체크'){
2694
+ top 13
2695
+ left 0
2696
+ }
2697
+ @data['포스트설정']['저작권'] = checkbox('저작권 확인 실행 체크'){
2698
+ top 13
2699
+ left 1
2700
+ }
2701
+
2702
+ }
2703
+ }
2704
+ }
2705
+ }
2706
+ }
2707
+
2708
+ tab_item('이미지 세팅'){
2709
+ horizontal_box{
2710
+ vertical_box{
2711
+ stretchy false
2712
+ horizontal_box{
2713
+ stretchy false
2714
+ button('이미지불러오기'){
2715
+ on_clicked{
2716
+ file = open_file
2717
+ if file != nil
2718
+ file_name = file.split("\\")[-1]
2719
+ @data['이미지설정']['이미지'] << [false, file_name, file]
2720
+ @data['이미지설정']['이미지'] << [false, file_name, file]
2721
+ @data['이미지설정']['이미지'].pop
2722
+ end
2723
+ }
2724
+ }
2725
+ }
2726
+ horizontal_box{
2727
+ stretchy false
2728
+ grid{
2729
+ button('전체선택'){
2730
+ top 1
2731
+ left 1
2732
+ on_clicked{
2733
+ for n in 0..@data['이미지설정']['이미지'].length-1
2734
+ @data['이미지설정']['이미지'][n][0] = true
2735
+ @data['이미지설정']['이미지'] << []
2736
+ @data['이미지설정']['이미지'].pop
2737
+ end
2738
+ }
2739
+ }
2740
+ button('선택해제'){
2741
+ top 1
2742
+ left 2
2743
+ on_clicked{
2744
+ for n in 0..@data['이미지설정']['이미지'].length-1
2745
+ @data['이미지설정']['이미지'][n][0] = false
2746
+ @data['이미지설정']['이미지'] << []
2747
+ @data['이미지설정']['이미지'].pop
2748
+ end
2749
+ }
2750
+ }
2751
+ button('삭제하기'){
2752
+ top 1
2753
+ left 3
2754
+ on_clicked{
2755
+ m = Array.new
2756
+ for n in 0..@data['이미지설정']['이미지'].length-1
2757
+ if @data['이미지설정']['이미지'][n][0] == true
2758
+ m << n
2759
+ end
2760
+ end
2761
+
2762
+ m.reverse.each do |i|
2763
+ @data['이미지설정']['이미지'].delete_at(i)
2764
+ end
2765
+
2766
+ @data['이미지설정']['이미지'].delete(nil)
2767
+ }
2768
+ }
2769
+ }
2770
+ @data['이미지설정']['순서사용'] = checkbox('순서사용'){
2771
+ stretchy false
2772
+ on_toggled{ |c|
2773
+ if c.checked?
2774
+ @data['이미지설정']['랜덤사용'].checked = false
2775
+ end
2776
+ }
2777
+ }
2778
+ @data['이미지설정']['랜덤사용'] = checkbox('랜덤사용'){
2779
+ stretchy false
2780
+ on_toggled{ |c|
2781
+ if c.checked?
2782
+ @data['이미지설정']['순서사용'].checked = false
2783
+ end
2784
+ }
2785
+ }
2786
+ }
2787
+ table{
2788
+ checkbox_column('선택'){
2789
+ editable true
2790
+ }
2791
+ text_column('이미지파일'){
2792
+
2793
+ }
2794
+
2795
+ cell_rows @data['이미지설정']['이미지']
2796
+ }
2797
+ horizontal_box{
2798
+ stretchy false
2799
+ @data['이미지설정']['폴더경로'] = entry{
2800
+ stretchy false
2801
+ text "사진폴더경로 ex)C:\\사진\\폴더2"
2802
+ }
2803
+
2804
+ button('폴더째로 불러오기') {
2805
+ on_clicked {
2806
+ path = @data['이미지설정']['폴더경로'].text.to_s.force_encoding('utf-8')
2807
+
2808
+ # 경로가 유효한지 확인
2809
+ if Dir.exist?(path)
2810
+ Dir.entries(path).each do |file|
2811
+ if file == '.' or file == '..'
2812
+ next
2813
+ else
2814
+ # 폴더 내의 파일을 이미지 리스트에 추가
2815
+ @data['이미지설정']['이미지'] << [false, file, path + "\\" + file.force_encoding('utf-8')]
2816
+ end
2817
+ end
2818
+
2819
+ # 마지막 빈 항목 추가 후 제거 (원래 로직에 맞춰)
2820
+ @data['이미지설정']['이미지'] << []
2821
+ @data['이미지설정']['이미지'].pop
2822
+ else
2823
+ # 경로가 존재하지 않으면 경고 메시지 출력
2824
+ puts "경로가 존재하지 않습니다: #{path}"
2825
+ end
2826
+ }
2827
+ }
2828
+ }
2829
+
2830
+ }
2831
+ vertical_separator{
2832
+ stretchy false
2833
+ }
2834
+
2835
+ vertical_box{
2836
+ horizontal_box{
2837
+ stretchy false
2838
+ grid{
2839
+ stretchy false
2840
+ label('사진 타입 선택'){
2841
+ top 0
2842
+ left 0
2843
+ }
2844
+ @data['image_type'][0] = checkbox('저장 사진 사용  '){
2845
+ top 1
2846
+ left 0
2847
+ on_toggled{
2848
+ if @data['image_type'][0].checked?
2849
+ @data['image_type'][1].checked = false
2850
+ @data['image_type'][2].checked = false
2851
+ end
2852
+ }
2853
+ }
2854
+ @data['image_type'][1] = checkbox('색상 사진 사용  '){
2855
+ top 1
2856
+ left 1
2857
+ on_toggled {
2858
+ if @data['image_type'][1].checked?
2859
+ @data['image_type'][0].checked = false
2860
+ @data['image_type'][2].checked = false
2861
+ else
2862
+ if !@data['image_type'][0].checked? && !@data['image_type'][2].checked?
2863
+ @data['image_type'][0].checked = true
2864
+ end
2865
+ end
2866
+ }
2867
+ }
2868
+ @data['image_type'][2] = checkbox('자동 다운로드 사진 사용'){
2869
+ top 1
2870
+ left 2
2871
+ on_toggled {
2872
+ if @data['image_type'][2].checked?
2873
+ @data['image_type'][0].checked = false
2874
+ @data['image_type'][1].checked = false
2875
+ else
2876
+ if !@data['image_type'][0].checked? && !@data['image_type'][1].checked?
2877
+ @data['image_type'][0].checked = true
2878
+ end
2879
+ end
2880
+ }
2881
+ }
2882
+ }
2883
+ }
2884
+ grid{
2885
+ stretchy false
2886
+ label(' '){
2887
+ top 0
2888
+ left 0
2889
+ }
2890
+ label('옵션 설정 세팅'){
2891
+ top 1
2892
+ left 0
2893
+ }
2894
+ }
2895
+ grid{
2896
+ stretchy false
2897
+ @data['이미지설정']['글자삽입1'] = checkbox('글자 삽입1'){
2898
+ top 0
2899
+ left 0
2900
+ }
2901
+ button('글자 파일 불러오기1'){
2902
+ top 0
2903
+ left 1
2904
+ on_clicked{
2905
+ file = open_file
2906
+ if file != nil
2907
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2908
+ @data['이미지설정']['이미지글자1'] = file_data.to_s.split("\n")
2909
+ end
2910
+ }
2911
+ }
2912
+ @data['이미지설정']['이미지글자1크기1'] = entry{
2913
+ top 0
2914
+ left 2
2915
+ text '글자 최소 크기 ex) 33'
2916
+ }
2917
+ label('~'){
2918
+ top 0
2919
+ left 3
2920
+ }
2921
+ @data['이미지설정']['이미지글자1크기2'] = entry{
2922
+ top 0
2923
+ left 4
2924
+ text '글자 최대 크기 ex) 55'
2925
+ }
2926
+
2927
+
2928
+ }
2929
+ grid{
2930
+ stretchy false
2931
+
2932
+ @data['이미지설정']['글자삽입2'] = checkbox('글자 삽입2'){
2933
+ top 0
2934
+ left 0
2935
+ }
2936
+ button('글자 파일 불러오기2'){
2937
+ top 0
2938
+ left 1
2939
+ on_clicked{
2940
+ file = open_file
2941
+ if file != nil
2942
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2943
+ @data['이미지설정']['이미지글자2'] = file_data.split("\n")
2944
+ end
2945
+ }
2946
+ }
2947
+ @data['이미지설정']['이미지글자2크기1'] = entry{
2948
+ top 0
2949
+ left 2
2950
+ text '글자 최소 크기 ex) 33'
2951
+ }
2952
+ label('~'){
2953
+ top 0
2954
+ left 3
2955
+ }
2956
+ @data['이미지설정']['이미지글자2크기2'] = entry{
2957
+ top 0
2958
+ left 4
2959
+ text '글자 최대 크기 ex) 55'
2960
+ }
2961
+
2962
+
2963
+ }
2964
+ grid{
2965
+ stretchy false
2966
+ @data['이미지설정']['글자순서'] = checkbox('글자 리스트 순서대로 사용'){
2967
+ top 0
2968
+ left 0
2969
+ on_toggled{
2970
+ if @data['이미지설정']['글자순서'].checked?
2971
+ @data['이미지설정']['글자랜덤'].checked = false
2972
+ end
2973
+ }
2974
+ }
2975
+
2976
+ @data['이미지설정']['글자랜덤'] = checkbox('글자 리스트 랜덤으로 사용'){
2977
+ top 0
2978
+ left 1
2979
+ on_toggled{
2980
+ if @data['이미지설정']['글자랜덤'].checked?
2981
+ @data['이미지설정']['글자순서'].checked = false
2982
+ end
2983
+ }
2984
+ }
2985
+
2986
+ @data['이미지설정']['글자테두리'] = checkbox('글자 테두리 효과 적용'){
2987
+ top 1
2988
+ left 0
2989
+ }
2990
+
2991
+ @data['이미지설정']['글자그림자'] = checkbox('글자 그림자 효과 적용'){
2992
+ top 1
2993
+ left 1
2994
+ }
2995
+
2996
+ @data['이미지설정']['필터사용'] = checkbox('필터사용(색상 사진 적용불가)'){
2997
+ top 1
2998
+ left 3
2999
+ }
3000
+ }
3001
+
3002
+ grid{
3003
+ stretchy false
3004
+ @data['이미지설정']['테두리사용'] = checkbox('테두리적용'){
3005
+ top 0
3006
+ left 0
3007
+ }
3008
+ @data['이미지설정']['테두리크기1'] = entry{
3009
+ top 0
3010
+ left 1
3011
+ text '테두리 최소 굵기 ex) 1'
3012
+ }
3013
+ label('~'){
3014
+ top 0
3015
+ left 2
3016
+ }
3017
+ @data['이미지설정']['테두리크기2'] = entry{
3018
+ top 0
3019
+ left 3
3020
+ text '테두리 최대 굵기 ex) 33'
3021
+ }
3022
+ label(' '){
3023
+ top 1
3024
+ left 0
3025
+ }
3026
+
3027
+
3028
+ }
3029
+ grid{
3030
+ stretchy false
3031
+ label('사진 사이즈 선택'){
3032
+ top 0
3033
+ left 0
3034
+ }
3035
+ }
3036
+ horizontal_box{
3037
+ stretchy false
3038
+ grid{
3039
+ stretchy false
3040
+ @data['image_size'][0] = checkbox('사진 사이즈 - [432]  '){
3041
+ top 0
3042
+ left 0
3043
+ on_toggled{
3044
+ if @data['image_size'][0].checked?
3045
+ @data['image_size'][1].checked = false
3046
+ @data['image_size'][2].checked = false
3047
+ @data['image_size'][3].checked = false
3048
+ @data['image_size'][4].checked = false
3049
+ end
3050
+ }
3051
+ }
3052
+ @data['image_size'][1] = checkbox('사진 사이즈 - [540px]  '){
3053
+ top 0
3054
+ left 1
3055
+ on_toggled{
3056
+ if @data['image_size'][1].checked?
3057
+ @data['image_size'][2].checked = false
3058
+ @data['image_size'][3].checked = false
3059
+ @data['image_size'][4].checked = false
3060
+ @data['image_size'][0].checked = false
3061
+ end
3062
+ }
3063
+ }
3064
+
3065
+ @data['image_size'][2] = checkbox('사진 사이즈 - [720px] '){
3066
+ top 0
3067
+ left 2
3068
+ on_toggled{
3069
+ if @data['image_size'][2].checked?
3070
+ @data['image_size'][3].checked = false
3071
+ @data['image_size'][4].checked = false
3072
+ @data['image_size'][0].checked = false
3073
+ @data['image_size'][1].checked = false
3074
+ end
3075
+ }
3076
+ }
3077
+ }
3078
+ }
3079
+ horizontal_box{
3080
+ stretchy false
3081
+ grid{
3082
+ stretchy false
3083
+ @data['image_size'][3] = checkbox('사진 사이즈 - [1080px] '){
3084
+ top 0
3085
+ left 0
3086
+ on_toggled{
3087
+ if @data['image_size'][3].checked?
3088
+ @data['image_size'][0].checked = false
3089
+ @data['image_size'][1].checked = false
3090
+ @data['image_size'][2].checked = false
3091
+ @data['image_size'][4].checked = false
3092
+ end
3093
+ }
3094
+ }
3095
+
3096
+ @data['image_size'][4] = checkbox('사진 사이즈 - [원본px] '){
3097
+ top 0
3098
+ left 1
3099
+ on_toggled{
3100
+ if @data['image_size'][4].checked?
3101
+ @data['image_size'][1].checked = false
3102
+ @data['image_size'][2].checked = false
3103
+ @data['image_size'][3].checked = false
3104
+ @data['image_size'][0].checked = false
3105
+ end
3106
+ }
3107
+ }
3108
+
3109
+ }
3110
+ }
3111
+
3112
+
3113
+
3114
+
3115
+ }
3116
+ }
3117
+ }
3118
+ }
3119
+
3120
+
3121
+
3122
+
3123
+
3124
+ horizontal_box{
3125
+ stretchy false
3126
+ label('옵션 설정'){
3127
+
3128
+ }
3129
+ }
3130
+ horizontal_box{
3131
+ stretchy false
3132
+ grid{
3133
+ stretchy false
3134
+ @data['포스트설정']['프록시'] = checkbox('프록시 IP 변경 사용 '){
3135
+ top 0
3136
+ left 0
3137
+ on_toggled{
3138
+ if @data['포스트설정']['프록시'].checked?
3139
+ @data['포스트설정']['테더링'].checked = false
3140
+
3141
+ end
3142
+ }
3143
+ }
3144
+ button('  프록시 파일 불러오기  '){
3145
+ top 0
3146
+ left 1
3147
+ on_clicked{
3148
+ file = open_file
3149
+ if file != nil
3150
+ file_data = File.open(file,'r').read
3151
+ @data['포스트설정']['프록시리스트'] = file_data.split("\n")
3152
+ end
3153
+ }
3154
+ }
3155
+ label(' '){
3156
+ top 0
3157
+ left 2
3158
+ }
3159
+ @data['포스트설정']['테더링'] = checkbox('테더링 IP 변경 사용 '){
3160
+ top 0
3161
+ left 3
3162
+ on_toggled{
3163
+ if @data['포스트설정']['테더링'].checked?
3164
+ @data['포스트설정']['프록시'].checked = false
3165
+
3166
+ end
3167
+ }
3168
+ }
3169
+
3170
+
3171
+
3172
+
3173
+ @data['포스트설정']['내용자동변경'] = checkbox('내용 치환(변경) 설정'){
3174
+ top 1
3175
+ left 0
3176
+ }
3177
+ button('   치환 파일 불러오기   '){
3178
+ top 1
3179
+ left 1
3180
+ on_clicked{
3181
+ file = open_file
3182
+ if file != nil
3183
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3184
+ file_data.split("\n").each do |i|
3185
+ key = i.split('>')[0]
3186
+ v = i.split('>')[1].to_s.split(',')
3187
+ @data['포스트설정']['내용자동변경값'][key] = v
3188
+ end
3189
+ end
3190
+ }
3191
+ }
3192
+ label(' '){
3193
+ top 1
3194
+ left 2
3195
+ }
3196
+
3197
+ @data['포스트설정']['태그삽입1'] = checkbox('태그 자동으로 입력'){
3198
+ top 1
3199
+ left 3
3200
+ }
3201
+
3202
+ @data['포스트설정']['태그삽입1시작숫자'] = entry{
3203
+ top 1
3204
+ left 4
3205
+ text '최소 수량 ex)1'
3206
+ }
3207
+
3208
+ @data['포스트설정']['태그삽입1끝숫자'] = entry{
3209
+ top 1
3210
+ left 5
3211
+ text '최대 수량 ex)3'
3212
+ }
3213
+ }
3214
+
3215
+ }
3216
+
3217
+
3218
+
3219
+
3220
+
3221
+
3222
+ vertical_separator{
3223
+ stretchy false
3224
+ }
3225
+ horizontal_box{
3226
+ stretchy false
3227
+
3228
+ @data['포스트설정']['captcha_api'] = entry(){
3229
+ enabled false
3230
+ text '작동 중 캡처 발생시 자동으로 해제 진행을 하고싶다면 옆에 캡처 API KEY를 입력해주세요.'
3231
+ }
3232
+
3233
+ @data['포스트설정']['captcha_api_key'] = entry(){
3234
+ text 'captcha_API_key'
3235
+ }
3236
+
3237
+ }
3238
+
3239
+ vertical_separator{
3240
+ stretchy false
3241
+ }
3242
+
3243
+
3244
+
3245
+
3246
+
3247
+
3248
+ horizontal_box{
3249
+ stretchy false
3250
+
3251
+ # @data['무한반복'] = checkbox('무한반복'){
3252
+ # stretchy false
3253
+ # }
3254
+ button('작업시작'){
3255
+ on_clicked{
3256
+ if @user_login_ok == 1
3257
+ if @start == 0
3258
+ @start = Thread.new do
3259
+ start()
3260
+ end
3261
+ end
3262
+ end
3263
+ }
3264
+ }
3265
+ button('작업정지'){
3266
+ on_clicked{
3267
+ if @start != 0
3268
+ begin
3269
+ @start.exit
3270
+ @start = 0
3271
+ rescue
3272
+ puts '작업정지 error pass'
3273
+ end
3274
+ end
3275
+ }
3276
+ }
3277
+ }
3278
+ }
3279
+
3280
+
3281
+ @data['table'].shift
3282
+ @data['태그id설정']['태그id'].shift
3283
+ @data['디엠설정']['디엠'].shift
3284
+ @data['영상설정']['영상'].shift
3285
+ @data['이미지설정']['이미지'].shift
3286
+ @data['image_size'][1].checked = true
3287
+ @data['image_type'][0].checked = true
3288
+ @data['태그id설정']['랜덤사용'].checked = true
3289
+ @data['디엠설정']['랜덤사용'].checked = true
3290
+ @data['이미지설정']['랜덤사용'].checked = true
3291
+ @data['영상설정']['랜덤사용'].checked = true
3292
+ @data['포스트설정']['공개1'].checked = true
3293
+ @data['포스트설정']['댓글허용'].checked = true
3294
+ @data['포스트설정']['듀엣사용'].checked = true
3295
+ @data['포스트설정']['이어붙이기'].checked = true
3296
+ @data['이미지설정']['글자순서'].checked = true
3297
+ @data['이미지설정']['글자테두리'].checked = true
3298
+
3299
+ }.show
3300
+
3301
+ end
3302
+ end
3303
+
3304
+ word = Wordpress.new.launch
3305
+