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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/tblog_duopack.rb +389 -254
  3. metadata +3 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2f27cbb2244157106fe1960abc0e33b43ca9df1da28ee0c0ddc47cfbf3346d5
4
- data.tar.gz: 8fdf4164701e3f939fe38dfddf19d66f31541e52784b147b5f46597f4da9f058
3
+ metadata.gz: 44cd103f7388e3c3b8d273b70b1e8e922d9c943f75c15b954f3c6b51bf9cae98
4
+ data.tar.gz: 96fe769e09a7a8dfd5654c4d12d9eede886dd61a1187ab149a9088a1d7257ac9
5
5
  SHA512:
6
- metadata.gz: d3e29ff309b404eaa6f51ed300261f482856d68d636a4ab43cb2df7f47c3b59fd24888c1a3c142298c0b764f3d3007c58761a73f414f2f6307e4aba1ef7321d2
7
- data.tar.gz: bc5fc5d68d9ac5484f7093cfb02b80375b36fdffaf8029d5628ad08c3396e5420d07dcfad22a18f24a90802a9705176ad47cfa6f6c00147139bf5f4ab485d818
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
- Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
253
- options = Selenium::WebDriver::Chrome::Options.new
254
- options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
255
- options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
256
- options.add_extension('./crx/app.crx') # 확장 프로그램을 첫 번째 탭에 추가
257
- options.add_argument('--disable-blink-features=AutomationControlled')
258
- options.add_argument('--disable-popup-blocking')
259
- options.add_argument('--dns-prefetch-disable')
260
- options.add_argument('--disable-dev-shm-usage')
261
- options.add_argument('--disable-software-rasterizer')
262
- options.add_argument('--ignore-certificate-errors')
263
- options.add_argument('--disable-gpu') # GPU 가속 끄기
264
- 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 위조
265
- options.add_argument('--disable-web-security')
266
- options.add_argument('--allow-running-insecure-content')
267
- options.add_argument('--allow-insecure-localhost')
268
- options.add_argument('--no-sandbox')
269
- options.add_argument('--disable-translate')
270
- options.add_argument('--disable-extensions-file-access-check')
271
- options.add_argument('--disable-impl-side-painting')
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
- options.exclude_switches = ['enable-automation']
275
-
276
- options.add_preference("profile.password_manager_enabled", false) # 비밀번호 관리자 비활성화
277
- options.add_preference("credentials_enable_service", false) # 비밀번호 저장 기능 비활성화
278
- #options.add_preference("profile.managed_default_content_settings.cookies", 2) # 쿠키 관련 팝업 차단
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
- # Proxy 설정
284
- if proxy != ''
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
- begin
290
- # 'capabilities'과 'options' 배열로 설정
291
- capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
292
- capabilities["goog:chromeOptions"] = options.as_json
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
- # Selenium 4에서는 'capabilities'만 사용하는 방식
295
- @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
312
+ # 현재 핸들 저장
313
+ main_tab = @driver.window_handle
296
314
 
297
- @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
298
-
299
- sleep(1)
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
- # Selenium 4에서는 'capabilities'만 사용하는 방식
313
- @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
319
+ @driver.switch_to.window(handle)
320
+ @driver.close # 다른 닫기
321
+ end
314
322
 
315
- @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
316
-
317
- # 첫 번째 탭에서 확장 프로그램을 로드
318
- #@driver.get("chrome-extension://ifibfemgeogfhoebkmokieepdoobkbpo/options/options.html")
319
- sleep(1)
320
- # 번째 탭에서 로그인 페이지 열기
321
- @driver.get('https://www.tistory.com/auth/login')
322
- sleep(1)
323
- end
324
- end
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
- user_cookie_file = []
332
- begin
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
- @cookie4 = {}
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
- begin
350
- @cookie4.each do |i|
351
- @driver.manage.add_cookie(name: i['name'], value: i['value'], same_site: i['same_site'], domain: i['domain'], path: i['path'])
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
- @driver.switch_to.window(@driver.window_handles.last)
357
- sleep(1.5)
358
- @driver.get('https://www.tistory.com/auth/login')
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
- @driver.switch_to.window(@driver.window_handles[0])
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 => 100)
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
- if @data['이미지설정']['순서사용'].checked?
1670
- image_path = @data['이미지설정']['이미지'][@image_counter][2]
1671
- @image_counter += 1
1672
- if @image_counter > @data['이미지설정']['이미지'].length-1
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
- img = Magick::Image.read(image_path).first
1679
- img.write('./image/memory.png')
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
- begin
1688
- if @data['image_type'][0].checked? or @data['image_type'][2].checked?
1689
- img.resize!(w, w*(height.to_f/width.to_f))
1690
- else
1691
- img.resize!(w, w)
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
- image_size = [480,740,650,550,480]
1782
+ # '원본'을 포함한 이미지 크기 옵션 추가
1783
+ image_size = [480, 740, 650, 550, 480, 'original']
1768
1784
  size = 0
1769
- for n in 0..4
1785
+
1786
+ for n in 0..5 # 0부터 5까지 반복, '원본' 옵션까지 포함
1770
1787
  if @data['image_size'][n].checked?
1771
- if n == 0
1772
- size = image_size.sample
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] = 35
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
- if @data['포스트설정']['gpt키워드'].checked?
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
- content5 = content.split("(자동생성글)")[0].to_s.split("\n")
2445
- content55 = content.split("(자동생성글)")[1].to_s if @data['포스트설정']['내용과자동생성'].checked? || @data['포스트설정']['gpt키워드'].checked?
2446
-
2447
- # 줄 찾기
2448
- empty_positions = content5.each_with_index.select { |line, index| line.strip.empty? }.map { |line, index| index }
2449
-
2450
- # 줄이 부족하면 텍스트 끝에 빈 줄 추가
2451
- if empty_positions.length < cn
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
- empty_positions = content5.each_with_index.select { |line, index| line.strip.empty? }.map { |line, index| index } # 다시 빈 줄 위치 계산
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
- position = empty_positions[0..cn-1]
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
- image_url22 = get_image_file().force_encoding('utf-8')
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
- image_url = get_image_file().force_encoding('utf-8')
2471
- puts '사진넣는위치 => ' + i.to_s
2472
-
2473
- # 링크가 있을 경우 링크 포함
2512
+ image_url22 = get_image_file().force_encoding('utf-8')
2474
2513
  if @data['포스트설정']['내용사진링크'].checked?
2475
- image_memory << "<a href='" + @data['포스트설정']['내용사진링크값'].text.to_s.force_encoding('utf-8') + "'><img src='" + image_url + "' alt='" + keyword.force_encoding('utf-8') + "'></a>"
2476
- content5[i] = '**image**' # 줄에 이미지를 삽입
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
- image_memory << "<img src='" + image_url + "' alt='" + keyword + "' class='aligncenter size-full'>"
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
- if @data['포스트설정']['내용과자동생성'].checked? || @data['포스트설정']['gpt키워드'].checked?
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
- if @data['포스트설정']['지도로변경'].checked?
2624
- @data['포스트설정']['지도로변경단어'].text.to_s.force_encoding('utf-8').split(',').each do |i|
2625
- content = content.split(i.force_encoding('utf-8')).join(" ""<koreamap>"+@data['포스트설정']['지도주소'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')+"</koreamap>")
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
- end
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
- if @data['포스트설정']['gpt키워드'].checked?
2642
- if @data['포스트설정']['gpt상단'].checked?
2643
- content = content_end+"\n"+content+"\n"
2644
- else
2645
- content = content+"\n"+content_end+"\n"
2646
- end
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
- content = content+"\n"+content_end+"\n"
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.33
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-02-13 00:00:00.000000000 Z
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.3.7
40
- signing_key:
37
+ rubygems_version: 3.6.7
41
38
  specification_version: 4
42
39
  summary: file to clipboard
43
40
  test_files: []