tblog_duopack 0.0.33 → 0.0.39
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.
- checksums.yaml +4 -4
- data/lib/tblog_duopack.rb +389 -254
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44cd103f7388e3c3b8d273b70b1e8e922d9c943f75c15b954f3c6b51bf9cae98
|
4
|
+
data.tar.gz: 96fe769e09a7a8dfd5654c4d12d9eede886dd61a1187ab149a9088a1d7257ac9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 005f2424612bab332af9179a7e25a49c7795ad52e2e4ab1a3b3da0d0599b4db504b7fe66e4be823a8f2bd8baf3397cfce4468d6a41dfaf531e4cabf502df83bf
|
7
|
+
data.tar.gz: 2201f3fdcfc633f45fddabee86f78d80ea6299c5acaba2eb0b65b88fe85180e68114e3ffee8047757bd39d8a7e0ff3c3fe9bb18e82f71ea5c52a530de95293f7
|
data/lib/tblog_duopack.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'glimmer-dsl-libui'
|
2
2
|
require 'selenium-webdriver'
|
3
|
-
# require 'webdrivers'
|
4
3
|
require 'iconv'
|
5
4
|
require 'nokogiri'
|
6
5
|
require 'http'
|
@@ -14,7 +13,6 @@ require 'clipboard'
|
|
14
13
|
require 'crack'
|
15
14
|
require 'uri'
|
16
15
|
require 'cgi'
|
17
|
-
require 'digest'
|
18
16
|
require 'auto_click'
|
19
17
|
require 'rainbow/refinement'
|
20
18
|
include AutoClickMethods
|
@@ -248,116 +246,186 @@ class Naver
|
|
248
246
|
end
|
249
247
|
|
250
248
|
def chrome_start(proxy)
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
249
|
+
# 공통 옵션 설정
|
250
|
+
begin
|
251
|
+
Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
|
252
|
+
rescue => e
|
253
|
+
puts "chromedriver 버전 불일치!!"
|
254
|
+
puts "아래 지침을 따라주세요."
|
255
|
+
puts "1.프로그램 종료!"
|
256
|
+
puts "2.크롬 업데이트!"
|
257
|
+
puts "3.프로그램 폴더 내부에 ★tip★-시작시-크롬창이....파일 실행"
|
258
|
+
puts "4.안내된 방식으로 크롬 드라이버 교체"
|
259
|
+
puts "5.재 시작"
|
260
|
+
exit 1
|
261
|
+
end
|
262
|
+
options = Selenium::WebDriver::Chrome::Options.new
|
263
|
+
options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
|
264
|
+
options.add_extension('./crx/app.crx') # 확장 프로그램을 첫 번째 탭에 추가
|
265
|
+
options.add_argument('--disable-blink-features=AutomationControlled')
|
266
|
+
options.add_argument('--disable-popup-blocking')
|
267
|
+
options.add_argument('--dns-prefetch-disable')
|
268
|
+
options.add_argument('--disable-dev-shm-usage')
|
269
|
+
options.add_argument('--disable-software-rasterizer')
|
270
|
+
options.add_argument('--ignore-certificate-errors')
|
271
|
+
options.add_argument('--disable-gpu') # GPU 가속 끄기
|
272
|
+
options.add_argument('user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36') # user-agent 위조
|
273
|
+
options.add_argument('--disable-web-security')
|
274
|
+
options.add_argument('--allow-running-insecure-content')
|
275
|
+
options.add_argument('--allow-insecure-localhost')
|
276
|
+
options.add_argument('--no-sandbox')
|
277
|
+
options.add_argument('--disable-translate')
|
278
|
+
options.add_argument('--disable-extensions-file-access-check')
|
279
|
+
options.add_argument('--disable-impl-side-painting')
|
280
|
+
options.add_argument('--log-level=3')
|
281
|
+
# 자동화된 테스트 제거
|
282
|
+
options.exclude_switches = ['enable-automation']
|
272
283
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
options.add_preference("profile.default_content_setting_values.notifications", 2) # 알림 차단
|
280
|
-
options.add_argument("--disable-save-password-bubble") # 비밀번호 저장 팝업 차단
|
284
|
+
options.add_preference("profile.password_manager_enabled", false) # 비밀번호 관리자 비활성화
|
285
|
+
options.add_preference("credentials_enable_service", false) # 비밀번호 저장 기능 비활성화
|
286
|
+
#options.add_preference("profile.managed_default_content_settings.cookies", 2) # 쿠키 관련 팝업 차단
|
287
|
+
options.add_preference("profile.default_content_setting_values.notifications", 2) # 알림 차단
|
288
|
+
options.add_argument("--disable-save-password-bubble") # 비밀번호 저장 팝업 차단
|
289
|
+
|
281
290
|
|
291
|
+
# Proxy 설정
|
292
|
+
if proxy != ''
|
293
|
+
options.add_argument('--proxy-server=' + proxy.to_s.force_encoding('utf-8'))
|
294
|
+
end
|
295
|
+
|
296
|
+
# 브라우저 실행
|
297
|
+
begin
|
298
|
+
# 'capabilities'과 'options' 배열로 설정
|
299
|
+
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
|
300
|
+
capabilities["goog:chromeOptions"] = options.as_json
|
282
301
|
|
283
|
-
|
284
|
-
|
285
|
-
options.add_argument('--proxy-server=' + proxy.to_s.force_encoding('utf-8'))
|
286
|
-
end
|
302
|
+
# Selenium 4에서는 'capabilities'만 사용하는 방식
|
303
|
+
@driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
|
287
304
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
305
|
+
@driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
|
306
|
+
|
307
|
+
sleep(1)
|
308
|
+
# 두 번째 탭에서 로그인 페이지 열기
|
309
|
+
@driver.get('https://www.tistory.com/auth/login')
|
310
|
+
sleep(1)
|
293
311
|
|
294
|
-
|
295
|
-
|
312
|
+
# 현재 탭 핸들 저장
|
313
|
+
main_tab = @driver.window_handle
|
296
314
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
# 두 번째 탭에서 로그인 페이지 열기
|
301
|
-
@driver.get('https://www.tistory.com/auth/login')
|
302
|
-
sleep(1)
|
303
|
-
|
304
|
-
rescue => e
|
305
|
-
|
306
|
-
puts "Error: #{e.message}"
|
307
|
-
puts 'Using default Chrome driver without proxy'
|
308
|
-
# 'capabilities'과 'options' 배열로 설정
|
309
|
-
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
|
310
|
-
capabilities["goog:chromeOptions"] = options.as_json
|
315
|
+
# 모든 탭 순회
|
316
|
+
@driver.window_handles.each do |handle|
|
317
|
+
next if handle == main_tab # 현재 탭은 남긴다
|
311
318
|
|
312
|
-
|
313
|
-
|
319
|
+
@driver.switch_to.window(handle)
|
320
|
+
@driver.close # 다른 탭 닫기
|
321
|
+
end
|
314
322
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
def login(user_id, user_pw, proxy, captcha_api_key)
|
327
|
-
chrome_start(proxy)
|
328
|
-
@captcha_api_key = captcha_api_key
|
329
|
-
@user_id = user_id
|
323
|
+
# 다시 로그인 탭으로 전환
|
324
|
+
@driver.switch_to.window(main_tab)
|
325
|
+
sleep(1)
|
326
|
+
rescue => e
|
327
|
+
|
328
|
+
puts "Error: #{e.message}"
|
329
|
+
puts 'Using default Chrome driver without proxy'
|
330
|
+
# 'capabilities'과 'options' 배열로 설정
|
331
|
+
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
|
332
|
+
capabilities["goog:chromeOptions"] = options.as_json
|
330
333
|
|
331
|
-
|
332
|
-
|
333
|
-
Dir.entries('./cookie').each do |i|
|
334
|
-
if i != '.' && i != '..'
|
335
|
-
user_cookie_file << i
|
336
|
-
end
|
337
|
-
end
|
338
|
-
rescue
|
339
|
-
end
|
334
|
+
# Selenium 4에서는 'capabilities'만 사용하는 방식
|
335
|
+
@driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
|
340
336
|
|
341
|
-
|
342
|
-
if user_cookie_file.include?(user_id+'.txt')
|
343
|
-
f = File.open('./cookie/'+user_id+'.txt', 'r')
|
344
|
-
@cookie4 = JSON.parse(f.read)
|
345
|
-
f.close
|
346
|
-
end
|
337
|
+
@driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
|
347
338
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
339
|
+
# 첫 번째 탭에서 확장 프로그램을 로드
|
340
|
+
#@driver.get("chrome-extension://ifibfemgeogfhoebkmokieepdoobkbpo/options/options.html")
|
341
|
+
sleep(1)
|
342
|
+
# 두 번째 탭에서 로그인 페이지 열기
|
343
|
+
@driver.get('https://www.tistory.com/auth/login')
|
344
|
+
sleep(1)
|
345
|
+
|
346
|
+
# 현재 탭 핸들 저장
|
347
|
+
main_tab = @driver.window_handle
|
348
|
+
|
349
|
+
# 모든 탭 순회
|
350
|
+
@driver.window_handles.each do |handle|
|
351
|
+
next if handle == main_tab # 현재 탭은 남긴다
|
352
|
+
|
353
|
+
@driver.switch_to.window(handle)
|
354
|
+
@driver.close # 다른 탭 닫기
|
355
|
+
end
|
356
|
+
|
357
|
+
# 다시 로그인 탭으로 전환
|
358
|
+
@driver.switch_to.window(main_tab)
|
359
|
+
sleep(1)
|
352
360
|
end
|
353
|
-
rescue
|
354
361
|
end
|
355
362
|
|
356
|
-
|
357
|
-
|
358
|
-
|
363
|
+
def login(user_id, user_pw, proxy, captcha_api_key)
|
364
|
+
chrome_start(proxy)
|
365
|
+
@captcha_api_key = captcha_api_key
|
366
|
+
@user_id = user_id
|
359
367
|
|
368
|
+
if captcha_api_key != 'captcha_api_key 입력' && !captcha_api_key.to_s.strip.empty?
|
369
|
+
puts "캡처 키 확인 됨: '#{captcha_api_key}'".red
|
370
|
+
@driver.switch_to.new_window(:tab)
|
371
|
+
sleep(1.5)
|
372
|
+
@driver.switch_to.window(@driver.window_handles[1])
|
373
|
+
@driver.navigate.to("chrome-extension://ifibfemgeogfhoebkmokieepdoobkbpo/options/options.html")
|
374
|
+
sleep(3)
|
375
|
+
@driver.find_element(:xpath, '//*[@name="apiKey"]').click
|
376
|
+
Clipboard.copy(captcha_api_key)
|
377
|
+
sleep(0.5)
|
378
|
+
@driver.action.key_down(:control).send_keys('v').key_up(:control).perform
|
379
|
+
sleep(0.5)
|
380
|
+
@driver.find_element(:xpath, '//*[@data-lang="login"]').click
|
381
|
+
|
382
|
+
begin
|
383
|
+
sleep(2)
|
384
|
+
@driver.switch_to.alert.dismiss
|
385
|
+
sleep(1)
|
386
|
+
rescue
|
387
|
+
end
|
388
|
+
@driver.close
|
389
|
+
sleep(1)
|
390
|
+
@driver.switch_to.window(@driver.window_handles[0])
|
391
|
+
sleep(2)
|
392
|
+
else
|
393
|
+
end
|
394
|
+
|
395
|
+
user_cookie_file = []
|
396
|
+
begin
|
397
|
+
Dir.entries('./cookie').each do |i|
|
398
|
+
if i != '.' && i != '..'
|
399
|
+
user_cookie_file << i
|
400
|
+
end
|
401
|
+
end
|
402
|
+
rescue
|
403
|
+
end
|
404
|
+
|
405
|
+
@cookie4 = {}
|
406
|
+
if user_cookie_file.include?(user_id+'.txt')
|
407
|
+
f = File.open('./cookie/'+user_id+'.txt', 'r')
|
408
|
+
@cookie4 = JSON.parse(f.read)
|
409
|
+
f.close
|
410
|
+
end
|
411
|
+
|
412
|
+
|
413
|
+
|
414
|
+
# 기존 쿠키가 있으면 쿠키를 추가
|
415
|
+
begin
|
416
|
+
@cookie4.each do |i|
|
417
|
+
@driver.manage.add_cookie(name: i['name'], value: i['value'], same_site: i['same_site'], domain: i['domain'], path: i['path'])
|
418
|
+
end
|
419
|
+
rescue
|
420
|
+
end
|
421
|
+
|
422
|
+
|
423
|
+
sleep(1.5)
|
424
|
+
@driver.get('https://www.tistory.com/auth/login')
|
360
425
|
sleep(1)
|
426
|
+
@driver.switch_to.window(@driver.window_handles[0])
|
427
|
+
|
428
|
+
|
361
429
|
begin
|
362
430
|
wait = Selenium::WebDriver::Wait.new(:timeout => 3)
|
363
431
|
wait.until { @driver.find_element(:xpath, '//*[@id="cMain"]/div/div/div/div/a[2]/span[2]') }
|
@@ -395,25 +463,7 @@ class Naver
|
|
395
463
|
wait.until { @driver.find_element(:xpath, '//*[@id="captchaContainer"]') }
|
396
464
|
puts '-[√] 로그인 중 캡챠 요구 발생 처리 진행.......'.yellow
|
397
465
|
sleep(1)
|
398
|
-
|
399
|
-
sleep(1)
|
400
|
-
@driver.find_element(:xpath, '//*[@name="apiKey"]').click
|
401
|
-
Clipboard.copy(captcha_api_key)
|
402
|
-
sleep(0.5)
|
403
|
-
@driver.action.key_down(:control).send_keys('v').key_up(:control).perform
|
404
|
-
sleep(0.5)
|
405
|
-
@driver.find_element(:xpath, '//*[@data-lang="login"]').click
|
406
|
-
|
407
|
-
begin
|
408
|
-
sleep(2)
|
409
|
-
@driver.switch_to.alert.dismiss
|
410
|
-
sleep(1)
|
411
|
-
rescue
|
412
|
-
|
413
|
-
end
|
414
|
-
|
415
|
-
# 두 번째 탭으로 전환
|
416
|
-
@driver.switch_to.window(@driver.window_handles[1])
|
466
|
+
|
417
467
|
|
418
468
|
begin
|
419
469
|
wait = Selenium::WebDriver::Wait.new(:timeout => 7)
|
@@ -519,6 +569,7 @@ class Naver
|
|
519
569
|
|
520
570
|
|
521
571
|
|
572
|
+
|
522
573
|
def update(title, content, option, url, keyword, captcha_api_key)#dd_time
|
523
574
|
puts 'start...'.yellow
|
524
575
|
puts(url)
|
@@ -541,20 +592,6 @@ class Naver
|
|
541
592
|
end
|
542
593
|
|
543
594
|
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
595
|
#@driver.manage.window.maximize
|
559
596
|
#창 크기 최대화
|
560
597
|
category2 = option['category'].to_s
|
@@ -579,12 +616,6 @@ class Naver
|
|
579
616
|
end
|
580
617
|
|
581
618
|
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
619
|
sleep(1)
|
589
620
|
|
590
621
|
begin
|
@@ -597,10 +628,6 @@ class Naver
|
|
597
628
|
puts e
|
598
629
|
end
|
599
630
|
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
631
|
|
605
632
|
|
606
633
|
sleep(1)
|
@@ -1240,29 +1267,7 @@ class Naver
|
|
1240
1267
|
wait.until { @driver.find_element(:xpath, '//*[@id="captchaContainer"]') }
|
1241
1268
|
puts '-[√] 로그인 중 캡챠 요구 발생 처리 진행.......'.yellow
|
1242
1269
|
sleep(1)
|
1243
|
-
@driver.switch_to.window(@driver.window_handles[0])
|
1244
|
-
sleep(1)
|
1245
|
-
@driver.find_element(:xpath, '//*[@name="apiKey"]').click
|
1246
|
-
sleep(0.5)
|
1247
|
-
@driver.find_element(:xpath, '//*[@name="apiKey"]').clear
|
1248
|
-
sleep(0.5)
|
1249
|
-
Clipboard.copy(captcha_api_key)
|
1250
|
-
sleep(0.5)
|
1251
|
-
@driver.action.key_down(:control).send_keys('v').key_up(:control).perform
|
1252
|
-
sleep(0.5)
|
1253
|
-
@driver.find_element(:xpath, '//*[@data-lang="login"]').click
|
1254
1270
|
|
1255
|
-
begin
|
1256
|
-
sleep(2)
|
1257
|
-
@driver.switch_to.alert.dismiss
|
1258
|
-
sleep(1)
|
1259
|
-
rescue
|
1260
|
-
|
1261
|
-
end
|
1262
|
-
|
1263
|
-
# 두 번째 탭으로 전환
|
1264
|
-
@driver.switch_to.window(@driver.window_handles[1])
|
1265
|
-
|
1266
1271
|
begin
|
1267
1272
|
wait = Selenium::WebDriver::Wait.new(:timeout => 7)
|
1268
1273
|
wait.until { @driver.find_element(:xpath, '//*[@data-state="ready"]') }
|
@@ -1391,7 +1396,7 @@ class Naver
|
|
1391
1396
|
@driver.find_element(:xpath, '//*[@id="publish-btn"]').click #등록완료버튼
|
1392
1397
|
rescue
|
1393
1398
|
# 타임아웃을 100초로 설정
|
1394
|
-
wait = Selenium::WebDriver::Wait.new(:timeout =>
|
1399
|
+
wait = Selenium::WebDriver::Wait.new(:timeout => 120)
|
1395
1400
|
# 요소가 나타날 때까지 100초 동안 기다립니다.
|
1396
1401
|
wait.until { @driver.find_element(:xpath, '//*[@data-state="solved"]') }
|
1397
1402
|
sleep(2)
|
@@ -1437,14 +1442,7 @@ class Naver
|
|
1437
1442
|
rescue
|
1438
1443
|
end
|
1439
1444
|
end
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1445
|
+
|
1448
1446
|
|
1449
1447
|
end
|
1450
1448
|
end
|
@@ -1664,35 +1662,52 @@ class Wordpress
|
|
1664
1662
|
|
1665
1663
|
def save_image
|
1666
1664
|
if @data['이미지설정']['이미지'].length == 0
|
1667
|
-
|
1665
|
+
return
|
1666
|
+
end
|
1667
|
+
|
1668
|
+
if @data['이미지설정']['순서사용'].checked?
|
1669
|
+
image_path = @data['이미지설정']['이미지'][@image_counter][2]
|
1670
|
+
@image_counter += 1
|
1671
|
+
if @image_counter > @data['이미지설정']['이미지'].length - 1
|
1672
|
+
@image_counter = 0
|
1673
|
+
end
|
1668
1674
|
else
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1673
|
-
@image_counter = 0
|
1674
|
-
end
|
1675
|
-
else
|
1676
|
-
image_path = @data['이미지설정']['이미지'].sample[2]
|
1675
|
+
# 초기화가 안됐거나 다 썼으면 새롭게 섞는다
|
1676
|
+
@shuffled_images ||= []
|
1677
|
+
if @shuffled_images.empty?
|
1678
|
+
@shuffled_images = @data['이미지설정']['이미지'].shuffle
|
1677
1679
|
end
|
1678
|
-
|
1679
|
-
|
1680
|
+
|
1681
|
+
image_path = @shuffled_images.shift[2]
|
1680
1682
|
end
|
1683
|
+
|
1684
|
+
img = Magick::Image.read(image_path).first
|
1685
|
+
img.write('./image/memory.png')
|
1681
1686
|
end
|
1682
1687
|
|
1683
1688
|
def change_image_size(w)
|
1684
1689
|
img = Magick::Image.read('./image/memory.png').first
|
1685
1690
|
width = img.columns
|
1686
1691
|
height = img.rows
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
+
|
1693
|
+
# '원본'이 선택된 경우, 리사이징을 하지 않고 원본 이미지를 그대로 반환
|
1694
|
+
if w == 'original'
|
1695
|
+
return img # 원본 이미지 그대로 반환
|
1696
|
+
else
|
1697
|
+
begin
|
1698
|
+
if @data['image_type'][0].checked? or @data['image_type'][2].checked?
|
1699
|
+
# 비율을 맞추어 리사이징
|
1700
|
+
img.resize!(w, w * (height.to_f / width.to_f))
|
1701
|
+
else
|
1702
|
+
# 정사각형으로 리사이징
|
1703
|
+
img.resize!(w, w)
|
1704
|
+
end
|
1705
|
+
rescue
|
1706
|
+
img.resize!(w, w) # 예외 처리 시에도 리사이징
|
1692
1707
|
end
|
1693
|
-
rescue
|
1694
|
-
img.resize!(w, w)
|
1695
1708
|
end
|
1709
|
+
|
1710
|
+
# 리사이징된 이미지 저장
|
1696
1711
|
img.write('./image/memory.png')
|
1697
1712
|
end
|
1698
1713
|
|
@@ -1764,22 +1779,28 @@ class Wordpress
|
|
1764
1779
|
auto_image()
|
1765
1780
|
end
|
1766
1781
|
|
1767
|
-
|
1782
|
+
# '원본'을 포함한 이미지 크기 옵션 추가
|
1783
|
+
image_size = [480, 740, 650, 550, 480, 'original']
|
1768
1784
|
size = 0
|
1769
|
-
|
1785
|
+
|
1786
|
+
for n in 0..5 # 0부터 5까지 반복, '원본' 옵션까지 포함
|
1770
1787
|
if @data['image_size'][n].checked?
|
1771
|
-
if n ==
|
1772
|
-
size =
|
1788
|
+
if n == 5 # '원본'이 선택되었을 경우
|
1789
|
+
size = 'original'
|
1790
|
+
elsif n == 0
|
1791
|
+
size = image_size.sample # 랜덤 선택
|
1773
1792
|
else
|
1774
1793
|
size = image_size[n]
|
1775
1794
|
end
|
1776
1795
|
end
|
1777
1796
|
end
|
1797
|
+
|
1798
|
+
# '원본'이 선택되지 않았다면 기본 값 설정
|
1778
1799
|
if size == 0
|
1779
1800
|
size = 480
|
1780
1801
|
end
|
1781
|
-
|
1782
|
-
change_image_size(size)
|
1802
|
+
|
1803
|
+
change_image_size(size) # 크기 변경 함수 호출
|
1783
1804
|
|
1784
1805
|
if @data['이미지설정']['필터사용'].checked?
|
1785
1806
|
image_filter()
|
@@ -2174,6 +2195,22 @@ class Wordpress
|
|
2174
2195
|
@data['table'].pop
|
2175
2196
|
#제목끝
|
2176
2197
|
# content = " #{content} "
|
2198
|
+
if @data['포스트설정']['gpt키워드'].checked?
|
2199
|
+
gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
|
2200
|
+
gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
|
2201
|
+
chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
|
2202
|
+
gpt_text = chat.message(keyword)
|
2203
|
+
#content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
|
2204
|
+
content = content.to_s + "(자동생성글)" + gpt_text.to_s
|
2205
|
+
elsif @data['포스트설정']['내용을자동생성'].checked?
|
2206
|
+
content = auto_text
|
2207
|
+
elsif @data['포스트설정']['내용과자동생성'].checked?
|
2208
|
+
#content = content + "\n(자동생성글)\n" + auto_text
|
2209
|
+
content = content + "(자동생성글)" + auto_text
|
2210
|
+
end
|
2211
|
+
@data['table'][index][-1] = 45
|
2212
|
+
@data['table'] << []
|
2213
|
+
@data['table'].pop
|
2177
2214
|
|
2178
2215
|
if @data['포스트설정']['특정단어굵기'].checked?
|
2179
2216
|
content2 = ''
|
@@ -2213,7 +2250,7 @@ class Wordpress
|
|
2213
2250
|
content = content2
|
2214
2251
|
end
|
2215
2252
|
end
|
2216
|
-
@data['table'][index][-1] =
|
2253
|
+
@data['table'][index][-1] = 50
|
2217
2254
|
@data['table'] << []
|
2218
2255
|
@data['table'].pop
|
2219
2256
|
if @data['포스트설정']['단어크기변경'].checked?
|
@@ -2234,19 +2271,7 @@ class Wordpress
|
|
2234
2271
|
@data['table'][index][-1] = 50
|
2235
2272
|
@data['table'] << []
|
2236
2273
|
@data['table'].pop
|
2237
|
-
|
2238
|
-
gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
|
2239
|
-
gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
|
2240
|
-
chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
|
2241
|
-
gpt_text = chat.message(keyword)
|
2242
|
-
#content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
|
2243
|
-
content = content.to_s + "(자동생성글)" + gpt_text.to_s
|
2244
|
-
elsif @data['포스트설정']['내용을자동생성'].checked?
|
2245
|
-
content = auto_text
|
2246
|
-
elsif @data['포스트설정']['내용과자동생성'].checked?
|
2247
|
-
#content = content + "\n(자동생성글)\n" + auto_text
|
2248
|
-
content = content + "(자동생성글)" + auto_text
|
2249
|
-
end
|
2274
|
+
|
2250
2275
|
|
2251
2276
|
if @data['포스트설정']['내용키워드삽입'].checked?
|
2252
2277
|
puts '내용키워드삽입...'
|
@@ -2428,7 +2453,6 @@ class Wordpress
|
|
2428
2453
|
|
2429
2454
|
if @data['포스트설정']['내용사진자동삽입'].checked?
|
2430
2455
|
puts '내용사진자동삽입...'
|
2431
|
-
|
2432
2456
|
sn = @data['포스트설정']['내용사진자동삽입시작숫자'].text.to_s.force_encoding('utf-8').to_i
|
2433
2457
|
en = @data['포스트설정']['내용사진자동삽입끝숫자'].text.to_s.force_encoding('utf-8').to_i
|
2434
2458
|
|
@@ -2440,54 +2464,71 @@ class Wordpress
|
|
2440
2464
|
end
|
2441
2465
|
|
2442
2466
|
if cn != 0
|
2443
|
-
#
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
missing_empty_lines = cn - empty_positions.length
|
2454
|
-
missing_empty_lines.times do
|
2455
|
-
content5 << "" # 텍스트 마지막에 빈 줄 추가
|
2467
|
+
# content5 구성 및 위치 배열 생성
|
2468
|
+
if @data['포스트설정']['내용과자동생성'].checked?
|
2469
|
+
if @data['포스트설정']['자동글 수식에 입력'].checked?
|
2470
|
+
content5 = content.split("(자동생성글)")[0].to_s.split("\n")
|
2471
|
+
content55 = content.split("(자동생성글)")[1].to_s
|
2472
|
+
position = content5.length.times.to_a.sample(cn).sort.reverse
|
2473
|
+
else
|
2474
|
+
content5 = content.split("(자동생성글)")[0].to_s.split("\n")
|
2475
|
+
content55 = content.split("(자동생성글)")[1].to_s
|
2476
|
+
position = content5.length.times.to_a.sample(cn).sort.reverse
|
2456
2477
|
end
|
2457
|
-
|
2478
|
+
elsif @data['포스트설정']['gpt키워드'].checked?
|
2479
|
+
content5 = content.split("(자동생성글)")[1].to_s.split("\n")
|
2480
|
+
content_prefix = content.split("(자동생성글)")[0].to_s
|
2481
|
+
content55 = ''
|
2482
|
+
position = content5.length.times.to_a.sample(cn).sort.reverse
|
2483
|
+
else
|
2484
|
+
content5 = content.split("\n")
|
2485
|
+
content55 = ''
|
2486
|
+
position = content5.length.times.to_a.sample(cn).sort.reverse
|
2458
2487
|
end
|
2459
2488
|
|
2460
|
-
#
|
2461
|
-
|
2489
|
+
# 중복 필터링 로직
|
2490
|
+
while true
|
2491
|
+
check11 = 0
|
2492
|
+
position.each_with_index do |pos, idx|
|
2493
|
+
if content5[pos].to_s.include?('style') || content5[pos].to_s.include?('<') || content5[pos].to_s.include?('>')
|
2494
|
+
check11 = 1
|
2495
|
+
position[idx] += 4
|
2496
|
+
end
|
2497
|
+
end
|
2498
|
+
break if check11 == 0
|
2499
|
+
end
|
2462
2500
|
|
2463
|
-
# 이미지 URL 가져오기
|
2464
2501
|
if @data['포스트설정']['내용과자동생성'].checked? || @data['포스트설정']['gpt키워드'].checked?
|
2465
|
-
|
2502
|
+
sleep(2)
|
2503
|
+
puts '이미지 자동 세탁 중 · · · '
|
2466
2504
|
end
|
2467
|
-
|
2468
|
-
|
2505
|
+
|
2506
|
+
p content5
|
2507
|
+
puts content55
|
2508
|
+
p position
|
2509
|
+
|
2510
|
+
sleep(2)
|
2469
2511
|
position.each do |i|
|
2470
|
-
|
2471
|
-
puts '사진넣는위치 => ' + i.to_s
|
2472
|
-
|
2473
|
-
# 링크가 있을 경우 링크 포함
|
2512
|
+
image_url22 = get_image_file().force_encoding('utf-8')
|
2474
2513
|
if @data['포스트설정']['내용사진링크'].checked?
|
2475
|
-
|
2476
|
-
|
2514
|
+
image_tag = '<a href="' + @data['포스트설정']['내용사진링크값'].text.to_s.force_encoding('utf-8') +
|
2515
|
+
'"><img src="' + image_url22 + '" alt="' + keyword.force_encoding('utf-8') + '" class="aligncenter size-full"></a>'
|
2477
2516
|
else
|
2478
|
-
|
2479
|
-
content5[i] = '**image**' # 빈 줄에 이미지를 삽입
|
2517
|
+
image_tag = '<img src="' + image_url22 + '" alt="' + keyword + '" class="aligncenter size-full">'
|
2480
2518
|
end
|
2519
|
+
content5.insert(i, image_tag)
|
2481
2520
|
end
|
2482
2521
|
|
2483
|
-
|
2484
|
-
|
2522
|
+
sleep(2)
|
2523
|
+
puts '이미지 자동 세탁 완료 · · · '
|
2524
|
+
|
2525
|
+
if @data['포스트설정']['내용과자동생성'].checked?
|
2485
2526
|
content = content5.join("\n") + '(자동생성글)' + content55
|
2527
|
+
elsif @data['포스트설정']['gpt키워드'].checked?
|
2528
|
+
content = content_prefix + "(자동생성글)" + content5.join("\n")
|
2486
2529
|
else
|
2487
2530
|
content = content5.join("\n")
|
2488
2531
|
end
|
2489
|
-
|
2490
|
-
puts content
|
2491
2532
|
end
|
2492
2533
|
end
|
2493
2534
|
|
@@ -2499,12 +2540,22 @@ class Wordpress
|
|
2499
2540
|
content = content_memory[0]
|
2500
2541
|
content_end = content_memory[1].to_s
|
2501
2542
|
|
2543
|
+
if @data['포스트설정']['gpt키워드'].checked?
|
2544
|
+
if @data['포스트설정']['gpt상단'].checked?
|
2545
|
+
content = "(자동생성글)\n" + content_end + "\n" + content
|
2546
|
+
else
|
2547
|
+
content = content + "\n(자동생성글)\n" + content_end
|
2548
|
+
end
|
2549
|
+
else
|
2550
|
+
content = content + "\n(자동생성글)\n" + content_end
|
2551
|
+
end
|
2552
|
+
|
2502
2553
|
if @data['포스트설정']['특정단어키워드로변경'].checked?
|
2503
2554
|
@data['포스트설정']['특정단어키워드로변경값'].text.to_s.force_encoding('utf-8').split(',').each do |i|
|
2504
2555
|
content = content.split(i.force_encoding('utf-8')).join(keyword)
|
2505
2556
|
end
|
2506
2557
|
end
|
2507
|
-
|
2558
|
+
|
2508
2559
|
@data['table'][index][-1] = 75
|
2509
2560
|
@data['table'] << []
|
2510
2561
|
@data['table'].pop
|
@@ -2620,11 +2671,76 @@ class Wordpress
|
|
2620
2671
|
# end
|
2621
2672
|
#end
|
2622
2673
|
|
2623
|
-
|
2624
|
-
@data['포스트설정']['
|
2625
|
-
|
2674
|
+
if @data['포스트설정']['지도로변경'].checked?
|
2675
|
+
map_address = @data['포스트설정']['지도주소'].text.to_s.force_encoding('utf-8')
|
2676
|
+
change_words = @data['포스트설정']['지도로변경단어'].text.to_s.force_encoding('utf-8').split(',')
|
2677
|
+
|
2678
|
+
content_lines = content.split("\n")
|
2679
|
+
new_lines = []
|
2680
|
+
|
2681
|
+
content_lines.each do |line|
|
2682
|
+
# 이미 처리된 줄은 건너뜀
|
2683
|
+
if line.include?("<koreamap>")
|
2684
|
+
new_lines << line
|
2685
|
+
next
|
2686
|
+
end
|
2687
|
+
|
2688
|
+
processed = false
|
2689
|
+
|
2690
|
+
change_words.each do |change_word|
|
2691
|
+
# 1. [단어][주소] 패턴 처리: 분리 + 출력
|
2692
|
+
if line =~ /#{Regexp.escape(change_word)}\[(.*?)\]/
|
2693
|
+
match_data = line.match(/(.*)#{Regexp.escape(change_word)}\[(.*?)\](.*)/)
|
2694
|
+
if match_data
|
2695
|
+
before = match_data[1]
|
2696
|
+
address = match_data[2]
|
2697
|
+
after = match_data[3]
|
2698
|
+
|
2699
|
+
# 태그 추출
|
2700
|
+
open_tag = before[/<p[^>]*?>/i] || ""
|
2701
|
+
close_tag = after[/<\/p>/i] || ""
|
2702
|
+
|
2703
|
+
# 텍스트 정리
|
2704
|
+
before_text = before.sub(open_tag, '')
|
2705
|
+
after_text = after.sub(close_tag, '')
|
2706
|
+
|
2707
|
+
# 줄 분리
|
2708
|
+
new_lines << "#{open_tag}#{before_text}</p>" unless before_text.strip.empty?
|
2709
|
+
new_lines << "<koreamap>#{address}</koreamap>"
|
2710
|
+
new_lines << "#{open_tag}#{after_text}#{close_tag}" unless after_text.strip.empty?
|
2711
|
+
|
2712
|
+
processed = true
|
2713
|
+
break
|
2714
|
+
end
|
2715
|
+
end
|
2716
|
+
|
2717
|
+
# 2. 일반 단어 처리 (한 줄에만 등장하는 경우)
|
2718
|
+
if !processed && line.include?(change_word)
|
2719
|
+
parts = line.split(change_word, 2)
|
2720
|
+
prefix = parts[0]
|
2721
|
+
suffix = parts[1]
|
2722
|
+
|
2723
|
+
open_tag = prefix[/<p[^>]*?>/i] || ""
|
2724
|
+
close_tag = suffix[/<\/p>/i] || ""
|
2725
|
+
|
2726
|
+
prefix_text = prefix.sub(open_tag, '')
|
2727
|
+
suffix_text = suffix.sub(close_tag, '')
|
2728
|
+
|
2729
|
+
new_lines << "#{open_tag}#{prefix_text}</p>" unless prefix_text.strip.empty?
|
2730
|
+
new_lines << "<koreamap>#{map_address}</koreamap>"
|
2731
|
+
new_lines << "#{open_tag}#{suffix_text}#{close_tag}" unless suffix_text.strip.empty?
|
2732
|
+
|
2733
|
+
processed = true
|
2734
|
+
break
|
2735
|
+
end
|
2736
|
+
end
|
2737
|
+
|
2738
|
+
# 변경이 없었으면 원래 줄 추가
|
2739
|
+
new_lines << line unless processed
|
2626
2740
|
end
|
2627
|
-
|
2741
|
+
|
2742
|
+
content = new_lines.join("\n")
|
2743
|
+
end
|
2628
2744
|
|
2629
2745
|
|
2630
2746
|
|
@@ -2638,15 +2754,18 @@ class Wordpress
|
|
2638
2754
|
# content = content
|
2639
2755
|
# soosick_1 = content_end
|
2640
2756
|
#else
|
2641
|
-
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
2646
|
-
|
2757
|
+
parts = content.split('(자동생성글)', 2)
|
2758
|
+
content_main = parts[0].strip
|
2759
|
+
content_end = parts[1].to_s.strip
|
2760
|
+
|
2761
|
+
if @data['포스트설정']['gpt키워드'].checked?
|
2762
|
+
if @data['포스트설정']['gpt상단'].checked?
|
2763
|
+
content = content_end + "\n" + content_main + "\n"
|
2647
2764
|
else
|
2648
|
-
|
2649
|
-
|
2765
|
+
content = content_main + "\n" + content_end + "\n"
|
2766
|
+
end
|
2767
|
+
else
|
2768
|
+
content = content_main + "\n" + content_end + "\n"
|
2650
2769
|
end
|
2651
2770
|
|
2652
2771
|
|
@@ -3935,6 +4054,7 @@ class Wordpress
|
|
3935
4054
|
@data['image_size'][2].checked = false
|
3936
4055
|
@data['image_size'][3].checked = false
|
3937
4056
|
@data['image_size'][4].checked = false
|
4057
|
+
@data['image_size'][5].checked = false
|
3938
4058
|
end
|
3939
4059
|
}
|
3940
4060
|
}
|
@@ -3945,6 +4065,7 @@ class Wordpress
|
|
3945
4065
|
@data['image_size'][2].checked = false
|
3946
4066
|
@data['image_size'][3].checked = false
|
3947
4067
|
@data['image_size'][4].checked = false
|
4068
|
+
@data['image_size'][5].checked = false
|
3948
4069
|
end
|
3949
4070
|
}
|
3950
4071
|
}
|
@@ -3955,6 +4076,7 @@ class Wordpress
|
|
3955
4076
|
@data['image_size'][0].checked = false
|
3956
4077
|
@data['image_size'][3].checked = false
|
3957
4078
|
@data['image_size'][4].checked = false
|
4079
|
+
@data['image_size'][5].checked = false
|
3958
4080
|
end
|
3959
4081
|
}
|
3960
4082
|
}
|
@@ -3965,6 +4087,7 @@ class Wordpress
|
|
3965
4087
|
@data['image_size'][2].checked = false
|
3966
4088
|
@data['image_size'][0].checked = false
|
3967
4089
|
@data['image_size'][4].checked = false
|
4090
|
+
@data['image_size'][5].checked = false
|
3968
4091
|
end
|
3969
4092
|
}
|
3970
4093
|
}
|
@@ -3975,6 +4098,18 @@ class Wordpress
|
|
3975
4098
|
@data['image_size'][2].checked = false
|
3976
4099
|
@data['image_size'][3].checked = false
|
3977
4100
|
@data['image_size'][0].checked = false
|
4101
|
+
@data['image_size'][5].checked = false
|
4102
|
+
end
|
4103
|
+
}
|
4104
|
+
}
|
4105
|
+
@data['image_size'][5] = checkbox('원본 px'){
|
4106
|
+
on_toggled{
|
4107
|
+
if @data['image_size'][5].checked?
|
4108
|
+
@data['image_size'][1].checked = false
|
4109
|
+
@data['image_size'][2].checked = false
|
4110
|
+
@data['image_size'][3].checked = false
|
4111
|
+
@data['image_size'][0].checked = false
|
4112
|
+
@data['image_size'][4].checked = false
|
3978
4113
|
end
|
3979
4114
|
}
|
3980
4115
|
}
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tblog_duopack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.39
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zon
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date: 2025-
|
10
|
+
date: 2025-05-12 00:00:00.000000000 Z
|
12
11
|
dependencies: []
|
13
12
|
description: File to Clipboard gem
|
14
13
|
email: mymin26@naver.com
|
@@ -21,7 +20,6 @@ homepage: ''
|
|
21
20
|
licenses:
|
22
21
|
- zon
|
23
22
|
metadata: {}
|
24
|
-
post_install_message:
|
25
23
|
rdoc_options: []
|
26
24
|
require_paths:
|
27
25
|
- lib
|
@@ -36,8 +34,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
36
34
|
- !ruby/object:Gem::Version
|
37
35
|
version: '0'
|
38
36
|
requirements: []
|
39
|
-
rubygems_version: 3.
|
40
|
-
signing_key:
|
37
|
+
rubygems_version: 3.6.7
|
41
38
|
specification_version: 4
|
42
39
|
summary: file to clipboard
|
43
40
|
test_files: []
|