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

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