tblog_zon 0.0.37 → 0.0.50

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_zon.rb +402 -236
  3. metadata +3 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf47eedcd16d949cc26c11e1df7774a35d204fe3be1b4dce0fa9552ecb15f573
4
- data.tar.gz: d878d55c3c9a52193dd4ed1aab77d21ef04213862783826f1d5afebf79dd35ba
3
+ metadata.gz: 06d765fda4fbf3a4758df37b162e7275cfb67fcd6980f42d0bd97d1707ffd85a
4
+ data.tar.gz: eab1e8cc76c8f0e1af500b180a4bffcf835e384da8732dd1e9966190f49c10b4
5
5
  SHA512:
6
- metadata.gz: 2e68d89074b522b6a31c8988126d1d8c295df50d6b9e63daac3f4fcdcdcdd4c1f78e4564833d7f18706fcac0c94aa86aca02d9bb976c2013be0c3f2b545c2c91
7
- data.tar.gz: 967c9982ee5fc281c395908199f6e69cb579e62b7eab213de0a990669c8af3a6c67cda28aa4abc257c05e211242381d38484bd0a02709620e255c3ba11d1b979
6
+ metadata.gz: 835975aa79061c10dfca5b8dfe06baaeeb94ee5fbfa33b49bf540265d255cad84c07a5c95655bdbf3bc6cc925f331e53547ba7e0a4602b64d8f86b0e7d67f0ff
7
+ data.tar.gz: 0a1439d23c400f2a3ae178cbaa870a38ba125cb65971fc8c489d56c6d5f51d189d972da9677745a127ffaced909a4890d041d48d32d6280f5e0669d88092c372
data/lib/tblog_zon.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,9 +13,9 @@ 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'
18
+ require 'httpclient'
20
19
  include AutoClickMethods
21
20
  using Rainbow
22
21
  include Glimmer
@@ -249,7 +248,18 @@ class Naver
249
248
 
250
249
  def chrome_start(proxy)
251
250
  # 공통 옵션 설정
252
- Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
251
+ begin
252
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
253
+ rescue => e
254
+ puts "chromedriver 버전 불일치!!"
255
+ puts "아래 지침을 따라주세요."
256
+ puts "1.프로그램 종료!"
257
+ puts "2.크롬 업데이트!"
258
+ puts "3.프로그램 폴더 내부에 ★tip★-시작시-크롬창이....파일 실행"
259
+ puts "4.안내된 방식으로 크롬 드라이버 교체"
260
+ puts "5.재 시작"
261
+ exit 1
262
+ end
253
263
  options = Selenium::WebDriver::Chrome::Options.new
254
264
  options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
255
265
  options.add_extension('./crx/app.crx') # 확장 프로그램을 첫 번째 탭에 추가
@@ -268,7 +278,7 @@ class Naver
268
278
  options.add_argument('--disable-translate')
269
279
  options.add_argument('--disable-extensions-file-access-check')
270
280
  options.add_argument('--disable-impl-side-painting')
271
-
281
+ options.add_argument('--log-level=3')
272
282
  # 자동화된 테스트 제거
273
283
  options.exclude_switches = ['enable-automation']
274
284
 
@@ -299,7 +309,21 @@ class Naver
299
309
  # 두 번째 탭에서 로그인 페이지 열기
300
310
  @driver.get('https://www.tistory.com/auth/login')
301
311
  sleep(1)
302
-
312
+
313
+ # 현재 탭 핸들 저장
314
+ main_tab = @driver.window_handle
315
+
316
+ # 모든 탭 순회
317
+ @driver.window_handles.each do |handle|
318
+ next if handle == main_tab # 현재 탭은 남긴다
319
+
320
+ @driver.switch_to.window(handle)
321
+ @driver.close # 다른 탭 닫기
322
+ end
323
+
324
+ # 다시 로그인 탭으로 전환
325
+ @driver.switch_to.window(main_tab)
326
+ sleep(1)
303
327
  rescue => e
304
328
 
305
329
  puts "Error: #{e.message}"
@@ -319,44 +343,90 @@ class Naver
319
343
  # 두 번째 탭에서 로그인 페이지 열기
320
344
  @driver.get('https://www.tistory.com/auth/login')
321
345
  sleep(1)
346
+
347
+ # 현재 탭 핸들 저장
348
+ main_tab = @driver.window_handle
349
+
350
+ # 모든 탭 순회
351
+ @driver.window_handles.each do |handle|
352
+ next if handle == main_tab # 현재 탭은 남긴다
353
+
354
+ @driver.switch_to.window(handle)
355
+ @driver.close # 다른 탭 닫기
356
+ end
357
+
358
+ # 다시 로그인 탭으로 전환
359
+ @driver.switch_to.window(main_tab)
360
+ sleep(1)
322
361
  end
323
362
  end
324
363
 
325
364
  def login(user_id, user_pw, proxy, captcha_api_key)
326
- chrome_start(proxy)
327
- @captcha_api_key = captcha_api_key
328
- @user_id = user_id
365
+ chrome_start(proxy)
366
+ @captcha_api_key = captcha_api_key
367
+ @user_id = user_id
329
368
 
330
- user_cookie_file = []
331
- begin
332
- Dir.entries('./cookie').each do |i|
333
- if i != '.' && i != '..'
334
- user_cookie_file << i
335
- end
369
+ if captcha_api_key != 'captcha_api_key 입력' && !captcha_api_key.to_s.strip.empty?
370
+ puts "캡처 키 확인 됨: '#{captcha_api_key}'".red
371
+ @driver.switch_to.new_window(:tab)
372
+ sleep(1.5)
373
+ @driver.switch_to.window(@driver.window_handles[1])
374
+ @driver.navigate.to("chrome-extension://ifibfemgeogfhoebkmokieepdoobkbpo/options/options.html")
375
+ sleep(3)
376
+ @driver.find_element(:xpath, '//*[@name="apiKey"]').click
377
+ Clipboard.copy(captcha_api_key)
378
+ sleep(0.5)
379
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
380
+ sleep(0.5)
381
+ @driver.find_element(:xpath, '//*[@data-lang="login"]').click
382
+
383
+ begin
384
+ sleep(2)
385
+ @driver.switch_to.alert.dismiss
386
+ sleep(1)
387
+ rescue
388
+ end
389
+ @driver.close
390
+ sleep(1)
391
+ @driver.switch_to.window(@driver.window_handles[0])
392
+ sleep(2)
393
+ else
394
+ end
395
+
396
+ user_cookie_file = []
397
+ begin
398
+ Dir.entries('./cookie').each do |i|
399
+ if i != '.' && i != '..'
400
+ user_cookie_file << i
401
+ end
402
+ end
403
+ rescue
336
404
  end
337
- rescue
338
- end
339
-
340
- @cookie4 = {}
341
- if user_cookie_file.include?(user_id+'.txt')
342
- f = File.open('./cookie/'+user_id+'.txt', 'r')
343
- @cookie4 = JSON.parse(f.read)
344
- f.close
345
- end
346
-
347
- # 기존 쿠키가 있으면 쿠키를 추가
348
- begin
349
- @cookie4.each do |i|
350
- @driver.manage.add_cookie(name: i['name'], value: i['value'], same_site: i['same_site'], domain: i['domain'], path: i['path'])
405
+
406
+ @cookie4 = {}
407
+ if user_cookie_file.include?(user_id+'.txt')
408
+ f = File.open('./cookie/'+user_id+'.txt', 'r')
409
+ @cookie4 = JSON.parse(f.read)
410
+ f.close
351
411
  end
352
- rescue
353
- end
354
-
355
- @driver.switch_to.window(@driver.window_handles.last)
356
- sleep(1.5)
357
- @driver.get('https://www.tistory.com/auth/login')
358
-
412
+
413
+
414
+
415
+ # 기존 쿠키가 있으면 쿠키를 추가
416
+ begin
417
+ @cookie4.each do |i|
418
+ @driver.manage.add_cookie(name: i['name'], value: i['value'], same_site: i['same_site'], domain: i['domain'], path: i['path'])
419
+ end
420
+ rescue
421
+ end
422
+
423
+
424
+ sleep(1.5)
425
+ @driver.get('https://www.tistory.com/auth/login')
359
426
  sleep(1)
427
+ @driver.switch_to.window(@driver.window_handles[0])
428
+
429
+
360
430
  begin
361
431
  wait = Selenium::WebDriver::Wait.new(:timeout => 3)
362
432
  wait.until { @driver.find_element(:xpath, '//*[@id="cMain"]/div/div/div/div/a[2]/span[2]') }
@@ -394,25 +464,7 @@ class Naver
394
464
  wait.until { @driver.find_element(:xpath, '//*[@id="captchaContainer"]') }
395
465
  puts '-[√] 로그인 중 캡챠 요구 발생 처리 진행.......'.yellow
396
466
  sleep(1)
397
- @driver.switch_to.window(@driver.window_handles[0])
398
- sleep(1)
399
- @driver.find_element(:xpath, '//*[@name="apiKey"]').click
400
- Clipboard.copy(captcha_api_key)
401
- sleep(0.5)
402
- @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
403
- sleep(0.5)
404
- @driver.find_element(:xpath, '//*[@data-lang="login"]').click
405
-
406
- begin
407
- sleep(2)
408
- @driver.switch_to.alert.dismiss
409
- sleep(1)
410
- rescue
411
-
412
- end
413
-
414
- # 두 번째 탭으로 전환
415
- @driver.switch_to.window(@driver.window_handles[1])
467
+
416
468
 
417
469
  begin
418
470
  wait = Selenium::WebDriver::Wait.new(:timeout => 7)
@@ -518,6 +570,7 @@ class Naver
518
570
 
519
571
 
520
572
 
573
+
521
574
  def update(title, content, option, url, keyword, captcha_api_key)#dd_time
522
575
  puts 'start...'.yellow
523
576
  puts(url)
@@ -540,20 +593,6 @@ class Naver
540
593
  end
541
594
 
542
595
 
543
-
544
-
545
-
546
-
547
-
548
-
549
-
550
-
551
-
552
-
553
-
554
-
555
-
556
-
557
596
  #@driver.manage.window.maximize
558
597
  #창 크기 최대화
559
598
  category2 = option['category'].to_s
@@ -578,12 +617,6 @@ class Naver
578
617
  end
579
618
 
580
619
 
581
-
582
-
583
-
584
-
585
-
586
-
587
620
  sleep(1)
588
621
 
589
622
  begin
@@ -596,10 +629,6 @@ class Naver
596
629
  puts e
597
630
  end
598
631
 
599
-
600
-
601
-
602
-
603
632
 
604
633
 
605
634
  sleep(1)
@@ -1239,29 +1268,7 @@ class Naver
1239
1268
  wait.until { @driver.find_element(:xpath, '//*[@id="captchaContainer"]') }
1240
1269
  puts '-[√] 로그인 중 캡챠 요구 발생 처리 진행.......'.yellow
1241
1270
  sleep(1)
1242
- @driver.switch_to.window(@driver.window_handles[0])
1243
- sleep(1)
1244
- @driver.find_element(:xpath, '//*[@name="apiKey"]').click
1245
- sleep(0.5)
1246
- @driver.find_element(:xpath, '//*[@name="apiKey"]').clear
1247
- sleep(0.5)
1248
- Clipboard.copy(captcha_api_key)
1249
- sleep(0.5)
1250
- @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
1251
- sleep(0.5)
1252
- @driver.find_element(:xpath, '//*[@data-lang="login"]').click
1253
1271
 
1254
- begin
1255
- sleep(2)
1256
- @driver.switch_to.alert.dismiss
1257
- sleep(1)
1258
- rescue
1259
-
1260
- end
1261
-
1262
- # 두 번째 탭으로 전환
1263
- @driver.switch_to.window(@driver.window_handles[1])
1264
-
1265
1272
  begin
1266
1273
  wait = Selenium::WebDriver::Wait.new(:timeout => 7)
1267
1274
  wait.until { @driver.find_element(:xpath, '//*[@data-state="ready"]') }
@@ -1390,7 +1397,7 @@ class Naver
1390
1397
  @driver.find_element(:xpath, '//*[@id="publish-btn"]').click #등록완료버튼
1391
1398
  rescue
1392
1399
  # 타임아웃을 100초로 설정
1393
- wait = Selenium::WebDriver::Wait.new(:timeout => 100)
1400
+ wait = Selenium::WebDriver::Wait.new(:timeout => 120)
1394
1401
  # 요소가 나타날 때까지 100초 동안 기다립니다.
1395
1402
  wait.until { @driver.find_element(:xpath, '//*[@data-state="solved"]') }
1396
1403
  sleep(2)
@@ -1436,14 +1443,7 @@ class Naver
1436
1443
  rescue
1437
1444
  end
1438
1445
  end
1439
-
1440
-
1441
-
1442
-
1443
-
1444
-
1445
-
1446
-
1446
+
1447
1447
 
1448
1448
  end
1449
1449
  end
@@ -1475,38 +1475,7 @@ class Wordpress
1475
1475
  end
1476
1476
  end
1477
1477
 
1478
- # def get_naver_text(q)
1479
- # begin
1480
- # Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
1481
- # @driver = Selenium::WebDriver.for :chrome
1482
- # rescue
1483
- # @driver = Selenium::WebDriver.for :chrome
1484
- # end
1485
- # @driver.get('https://search.naver.com/search.naver?display=15&f=&filetype=0&page=3&query='+q.to_s+'&research_url=&sm=tab_pge&start=16&where=web')
1486
- # noko = Nokogiri::HTML(@driver.page_source)
1487
- # tt = noko.xpath('//*[@id="main_pack"]/section/div/ul').text
1488
- # aa33 = '하였습니다,하였어요,하게됬어요,했답니다,했었는데요,하게되었어요,했어요,그랬답니다,그랬어요,합니다,그랬어요,그랬답니다,그랬답니다,그러합니다,좋아요,좋습니다,됬어요,되었어요,되었답니다,되었구요,되었어요,되네요,하네요,해요,할거예요,할수었이요,입니다,인데요,이예요,이랍니다,이였어요,그랬어요,그랬거든요,그랬습니다,었어요,었습니다,있었어요'.split(',')
1489
- # for page in 3..8
1490
- # @driver.get('https://www.google.com/search?q='+q.to_s+'&start='+(page*10).to_s)
1491
- # noko = Nokogiri::HTML(@driver.page_source)
1492
- # for n in 1..15
1493
- # tt2 = noko.xpath('//*[@id="rso"]/div['+n.to_s+']/div/div/div[2]/div').text
1494
- # if tt2.length < 5
1495
-
1496
- # else
1497
- # tt2 = tt2.split('...').join('')+aa3.sample
1498
- # tt += tt2
1499
- # end
1500
- # end
1501
- # end
1502
- # @driver.close
1503
- # tt = tt.split(' ').shuffle.join(' ')[0..1000]
1504
- # m = Array.new
1505
- # for n in 0..19
1506
- # m << tt[(n*100)..(n*100+100)]
1507
- # end
1508
- # return m.join("\n")
1509
- # end
1478
+
1510
1479
 
1511
1480
  def get_naver_text(q)
1512
1481
  begin
@@ -1598,21 +1567,81 @@ class Wordpress
1598
1567
 
1599
1568
 
1600
1569
 
1601
- def auto_image
1570
+ def auto_image(keyword = nil)
1571
+ keyword ||= @keyword
1572
+ puts "키워드: #{keyword}"
1573
+
1574
+ client = HTTPClient.new
1575
+ client.default_header = {
1576
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
1577
+ '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
1578
+ 'Accept' => 'application/json, text/javascript, */*; q=0.01',
1579
+ 'Accept-Language' => 'en-US,en;q=0.9',
1580
+ 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
1581
+ 'X-Requested-With' => 'XMLHttpRequest'
1582
+ }
1583
+
1584
+ retry_count = 0
1585
+ max_retries = 10
1586
+ results = []
1587
+
1602
1588
  begin
1603
1589
  page = rand(1..15)
1604
- http = HTTP.get('https://unsplash.com/napi/photos?per_page=12&page='+page.to_s)
1605
- json = JSON.parse(http.to_s)
1606
- mm = Array.new
1607
- json.each do |i|
1608
- mm << i['urls']['full']
1590
+ url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
1591
+ puts "Request URL: #{url}"
1592
+ res = client.get(url)
1593
+
1594
+ unless res.status == 200
1595
+ puts "HTTP Error: #{res.status}"
1596
+ raise "HTTP Error"
1609
1597
  end
1610
- url = mm.sample
1611
- Down.download(url, destination: "./image/memory.png")
1612
- rescue
1613
- puts 'auto_image 일시적 error 5초후 제시도...'
1614
- sleep(5)
1598
+
1599
+ json = JSON.parse(res.body)
1600
+ results = json['results']
1601
+ mm = []
1602
+
1603
+ results.each do |photo|
1604
+ full_url = photo.dig('urls', 'full').to_s
1605
+ regular_url = photo.dig('urls', 'regular').to_s
1606
+
1607
+ if full_url.start_with?("https://images.unsplash.com/photo-") &&
1608
+ regular_url.include?("1080")
1609
+ mm << full_url
1610
+ end
1611
+ end
1612
+
1613
+ if mm.empty?
1614
+ raise "No matching image"
1615
+ end
1616
+
1617
+ selected_url = mm.sample
1618
+ Down.download(selected_url, destination: "./image/memory.png")
1619
+ puts "이미지 다운로드 완료: #{selected_url}"
1620
+
1621
+ rescue => e
1622
+ retry_count += 1
1623
+ puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
1624
+ sleep(3)
1625
+ if retry_count < max_retries
1615
1626
  retry
1627
+ else
1628
+ puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
1629
+
1630
+ if results && !results.empty?
1631
+ random_photo = results.sample
1632
+ fallback_url = random_photo.dig('urls', 'full')
1633
+ if fallback_url
1634
+ Down.download(fallback_url, destination: "./image/memory.png")
1635
+ puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
1636
+ else
1637
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
1638
+ color_image
1639
+ end
1640
+ else
1641
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
1642
+ color_image
1643
+ end
1644
+ end
1616
1645
  end
1617
1646
  end
1618
1647
 
@@ -1624,35 +1653,52 @@ class Wordpress
1624
1653
 
1625
1654
  def save_image
1626
1655
  if @data['이미지설정']['이미지'].length == 0
1627
-
1656
+ return
1657
+ end
1658
+
1659
+ if @data['이미지설정']['순서사용'].checked?
1660
+ image_path = @data['이미지설정']['이미지'][@image_counter][2]
1661
+ @image_counter += 1
1662
+ if @image_counter > @data['이미지설정']['이미지'].length - 1
1663
+ @image_counter = 0
1664
+ end
1628
1665
  else
1629
- if @data['이미지설정']['순서사용'].checked?
1630
- image_path = @data['이미지설정']['이미지'][@image_counter][2]
1631
- @image_counter += 1
1632
- if @image_counter > @data['이미지설정']['이미지'].length-1
1633
- @image_counter = 0
1634
- end
1635
- else
1636
- image_path = @data['이미지설정']['이미지'].sample[2]
1666
+ # 초기화가 안됐거나 다 썼으면 새롭게 섞는다
1667
+ @shuffled_images ||= []
1668
+ if @shuffled_images.empty?
1669
+ @shuffled_images = @data['이미지설정']['이미지'].shuffle
1637
1670
  end
1638
- img = Magick::Image.read(image_path).first
1639
- img.write('./image/memory.png')
1671
+
1672
+ image_path = @shuffled_images.shift[2]
1640
1673
  end
1674
+
1675
+ img = Magick::Image.read(image_path).first
1676
+ img.write('./image/memory.png')
1641
1677
  end
1642
1678
 
1643
1679
  def change_image_size(w)
1644
1680
  img = Magick::Image.read('./image/memory.png').first
1645
1681
  width = img.columns
1646
1682
  height = img.rows
1647
- begin
1648
- if @data['image_type'][0].checked? or @data['image_type'][2].checked?
1649
- img.resize!(w, w*(height.to_f/width.to_f))
1650
- else
1651
- img.resize!(w, w)
1683
+
1684
+ # '원본' 선택된 경우, 리사이징을 하지 않고 원본 이미지를 그대로 반환
1685
+ if w == 'original'
1686
+ return img # 원본 이미지 그대로 반환
1687
+ else
1688
+ begin
1689
+ if @data['image_type'][0].checked? or @data['image_type'][2].checked?
1690
+ # 비율을 맞추어 리사이징
1691
+ img.resize!(w, w * (height.to_f / width.to_f))
1692
+ else
1693
+ # 정사각형으로 리사이징
1694
+ img.resize!(w, w)
1695
+ end
1696
+ rescue
1697
+ img.resize!(w, w) # 예외 처리 시에도 리사이징
1652
1698
  end
1653
- rescue
1654
- img.resize!(w, w)
1655
1699
  end
1700
+
1701
+ # 리사이징된 이미지 저장
1656
1702
  img.write('./image/memory.png')
1657
1703
  end
1658
1704
 
@@ -1724,22 +1770,28 @@ class Wordpress
1724
1770
  auto_image()
1725
1771
  end
1726
1772
 
1727
- image_size = [480,740,650,550,480]
1773
+ # '원본'을 포함한 이미지 크기 옵션 추가
1774
+ image_size = [480, 740, 650, 550, 480, 'original']
1728
1775
  size = 0
1729
- for n in 0..4
1776
+
1777
+ for n in 0..5 # 0부터 5까지 반복, '원본' 옵션까지 포함
1730
1778
  if @data['image_size'][n].checked?
1731
- if n == 0
1732
- size = image_size.sample
1779
+ if n == 5 # '원본'이 선택되었을 경우
1780
+ size = 'original'
1781
+ elsif n == 0
1782
+ size = image_size.sample # 랜덤 선택
1733
1783
  else
1734
1784
  size = image_size[n]
1735
1785
  end
1736
1786
  end
1737
1787
  end
1788
+
1789
+ # '원본'이 선택되지 않았다면 기본 값 설정
1738
1790
  if size == 0
1739
1791
  size = 480
1740
1792
  end
1741
-
1742
- change_image_size(size)
1793
+
1794
+ change_image_size(size) # 크기 변경 함수 호출
1743
1795
 
1744
1796
  if @data['이미지설정']['필터사용'].checked?
1745
1797
  image_filter()
@@ -2134,6 +2186,22 @@ class Wordpress
2134
2186
  @data['table'].pop
2135
2187
  #제목끝
2136
2188
  # content = " #{content} "
2189
+ if @data['포스트설정']['gpt키워드'].checked?
2190
+ gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
2191
+ gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
2192
+ chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
2193
+ gpt_text = chat.message(keyword)
2194
+ #content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
2195
+ content = content.to_s + "(자동생성글)" + gpt_text.to_s
2196
+ elsif @data['포스트설정']['내용을자동생성'].checked?
2197
+ content = auto_text
2198
+ elsif @data['포스트설정']['내용과자동생성'].checked?
2199
+ #content = content + "\n(자동생성글)\n" + auto_text
2200
+ content = content + "(자동생성글)" + auto_text
2201
+ end
2202
+ @data['table'][index][-1] = 45
2203
+ @data['table'] << []
2204
+ @data['table'].pop
2137
2205
 
2138
2206
  if @data['포스트설정']['특정단어굵기'].checked?
2139
2207
  content2 = ''
@@ -2173,7 +2241,7 @@ class Wordpress
2173
2241
  content = content2
2174
2242
  end
2175
2243
  end
2176
- @data['table'][index][-1] = 35
2244
+ @data['table'][index][-1] = 50
2177
2245
  @data['table'] << []
2178
2246
  @data['table'].pop
2179
2247
  if @data['포스트설정']['단어크기변경'].checked?
@@ -2194,19 +2262,7 @@ class Wordpress
2194
2262
  @data['table'][index][-1] = 50
2195
2263
  @data['table'] << []
2196
2264
  @data['table'].pop
2197
- if @data['포스트설정']['gpt키워드'].checked?
2198
- gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
2199
- gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
2200
- chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
2201
- gpt_text = chat.message(keyword)
2202
- #content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
2203
- content = content.to_s + "(자동생성글)" + gpt_text.to_s
2204
- elsif @data['포스트설정']['내용을자동생성'].checked?
2205
- content = auto_text
2206
- elsif @data['포스트설정']['내용과자동생성'].checked?
2207
- #content = content + "\n(자동생성글)\n" + auto_text
2208
- content = content + "(자동생성글)" + auto_text
2209
- end
2265
+
2210
2266
 
2211
2267
  if @data['포스트설정']['내용키워드삽입'].checked?
2212
2268
  puts '내용키워드삽입...'
@@ -2388,7 +2444,6 @@ class Wordpress
2388
2444
 
2389
2445
  if @data['포스트설정']['내용사진자동삽입'].checked?
2390
2446
  puts '내용사진자동삽입...'
2391
-
2392
2447
  sn = @data['포스트설정']['내용사진자동삽입시작숫자'].text.to_s.force_encoding('utf-8').to_i
2393
2448
  en = @data['포스트설정']['내용사진자동삽입끝숫자'].text.to_s.force_encoding('utf-8').to_i
2394
2449
 
@@ -2400,54 +2455,71 @@ class Wordpress
2400
2455
  end
2401
2456
 
2402
2457
  if cn != 0
2403
- # 내용 분할 (자동 생성 글과 텍스트)
2404
- content5 = content.split("(자동생성글)")[0].to_s.split("\n")
2405
- content55 = content.split("(자동생성글)")[1].to_s if @data['포스트설정']['내용과자동생성'].checked? || @data['포스트설정']['gpt키워드'].checked?
2406
-
2407
- # 줄 찾기
2408
- empty_positions = content5.each_with_index.select { |line, index| line.strip.empty? }.map { |line, index| index }
2409
-
2410
- # 줄이 부족하면 텍스트 끝에 빈 줄 추가
2411
- if empty_positions.length < cn
2412
- # 부족한 빈 줄의 수
2413
- missing_empty_lines = cn - empty_positions.length
2414
- missing_empty_lines.times do
2415
- content5 << "" # 텍스트 마지막에 빈 줄 추가
2458
+ # content5 구성 위치 배열 생성
2459
+ if @data['포스트설정']['내용과자동생성'].checked?
2460
+ if @data['포스트설정']['자동글 수식에 입력'].checked?
2461
+ content5 = content.split("(자동생성글)")[0].to_s.split("\n")
2462
+ content55 = content.split("(자동생성글)")[1].to_s
2463
+ position = content5.length.times.to_a.sample(cn).sort.reverse
2464
+ else
2465
+ content5 = content.split("(자동생성글)")[0].to_s.split("\n")
2466
+ content55 = content.split("(자동생성글)")[1].to_s
2467
+ position = content5.length.times.to_a.sample(cn).sort.reverse
2416
2468
  end
2417
- empty_positions = content5.each_with_index.select { |line, index| line.strip.empty? }.map { |line, index| index } # 다시 빈 줄 위치 계산
2469
+ elsif @data['포스트설정']['gpt키워드'].checked?
2470
+ content5 = content.split("(자동생성글)")[1].to_s.split("\n")
2471
+ content_prefix = content.split("(자동생성글)")[0].to_s
2472
+ content55 = ''
2473
+ position = content5.length.times.to_a.sample(cn).sort.reverse
2474
+ else
2475
+ content5 = content.split("\n")
2476
+ content55 = ''
2477
+ position = content5.length.times.to_a.sample(cn).sort.reverse
2418
2478
  end
2419
2479
 
2420
- # 이미지 삽입할 위치를 지정 (빈 줄 위치에 삽입)
2421
- position = empty_positions[0..cn-1]
2480
+ # 중복 필터링 로직
2481
+ while true
2482
+ check11 = 0
2483
+ position.each_with_index do |pos, idx|
2484
+ if content5[pos].to_s.include?('style') || content5[pos].to_s.include?('<') || content5[pos].to_s.include?('>')
2485
+ check11 = 1
2486
+ position[idx] += 4
2487
+ end
2488
+ end
2489
+ break if check11 == 0
2490
+ end
2422
2491
 
2423
- # 이미지 URL 가져오기
2424
2492
  if @data['포스트설정']['내용과자동생성'].checked? || @data['포스트설정']['gpt키워드'].checked?
2425
- image_url22 = get_image_file().force_encoding('utf-8')
2493
+ sleep(2)
2494
+ puts '이미지 자동 세탁 중 · · · '
2426
2495
  end
2427
-
2428
- # 각 위치에 이미지를 하나씩만 삽입
2496
+
2497
+ p content5
2498
+ puts content55
2499
+ p position
2500
+
2501
+ sleep(2)
2429
2502
  position.each do |i|
2430
- image_url = get_image_file().force_encoding('utf-8')
2431
- puts '사진넣는위치 => ' + i.to_s
2432
-
2433
- # 링크가 있을 경우 링크 포함
2503
+ image_url22 = get_image_file().force_encoding('utf-8')
2434
2504
  if @data['포스트설정']['내용사진링크'].checked?
2435
- image_memory << "<a href='" + @data['포스트설정']['내용사진링크값'].text.to_s.force_encoding('utf-8') + "'><img src='" + image_url + "' alt='" + keyword.force_encoding('utf-8') + "'></a>"
2436
- content5[i] = '**image**' # 줄에 이미지를 삽입
2505
+ image_tag = '<a href="' + @data['포스트설정']['내용사진링크값'].text.to_s.force_encoding('utf-8') +
2506
+ '"><img src="' + image_url22 + '" alt="' + keyword.force_encoding('utf-8') + '" class="aligncenter size-full"></a>'
2437
2507
  else
2438
- image_memory << "<img src='" + image_url + "' alt='" + keyword + "' class='aligncenter size-full'>"
2439
- content5[i] = '**image**' # 빈 줄에 이미지를 삽입
2508
+ image_tag = '<img src="' + image_url22 + '" alt="' + keyword + '" class="aligncenter size-full">'
2440
2509
  end
2510
+ content5.insert(i, image_tag)
2441
2511
  end
2442
2512
 
2443
- # 자동 생성된 내용과 합치기
2444
- if @data['포스트설정']['내용과자동생성'].checked? || @data['포스트설정']['gpt키워드'].checked?
2513
+ sleep(2)
2514
+ puts '이미지 자동 세탁 완료 · · · '
2515
+
2516
+ if @data['포스트설정']['내용과자동생성'].checked?
2445
2517
  content = content5.join("\n") + '(자동생성글)' + content55
2518
+ elsif @data['포스트설정']['gpt키워드'].checked?
2519
+ content = content_prefix + "(자동생성글)" + content5.join("\n")
2446
2520
  else
2447
2521
  content = content5.join("\n")
2448
2522
  end
2449
-
2450
- puts content
2451
2523
  end
2452
2524
  end
2453
2525
 
@@ -2459,12 +2531,22 @@ class Wordpress
2459
2531
  content = content_memory[0]
2460
2532
  content_end = content_memory[1].to_s
2461
2533
 
2534
+ if @data['포스트설정']['gpt키워드'].checked?
2535
+ if @data['포스트설정']['gpt상단'].checked?
2536
+ content = "(자동생성글)\n" + content_end + "\n" + content
2537
+ else
2538
+ content = content + "\n(자동생성글)\n" + content_end
2539
+ end
2540
+ else
2541
+ content = content + "\n(자동생성글)\n" + content_end
2542
+ end
2543
+
2462
2544
  if @data['포스트설정']['특정단어키워드로변경'].checked?
2463
2545
  @data['포스트설정']['특정단어키워드로변경값'].text.to_s.force_encoding('utf-8').split(',').each do |i|
2464
2546
  content = content.split(i.force_encoding('utf-8')).join(keyword)
2465
2547
  end
2466
2548
  end
2467
-
2549
+
2468
2550
  @data['table'][index][-1] = 75
2469
2551
  @data['table'] << []
2470
2552
  @data['table'].pop
@@ -2580,11 +2662,76 @@ class Wordpress
2580
2662
  # end
2581
2663
  #end
2582
2664
 
2583
- if @data['포스트설정']['지도로변경'].checked?
2584
- @data['포스트설정']['지도로변경단어'].text.to_s.force_encoding('utf-8').split(',').each do |i|
2585
- content = content.split(i.force_encoding('utf-8')).join(" ""<koreamap>"+@data['포스트설정']['지도주소'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')+"</koreamap>")
2665
+ if @data['포스트설정']['지도로변경'].checked?
2666
+ map_address = @data['포스트설정']['지도주소'].text.to_s.force_encoding('utf-8')
2667
+ change_words = @data['포스트설정']['지도로변경단어'].text.to_s.force_encoding('utf-8').split(',')
2668
+
2669
+ content_lines = content.split("\n")
2670
+ new_lines = []
2671
+
2672
+ content_lines.each do |line|
2673
+ # 이미 처리된 줄은 건너뜀
2674
+ if line.include?("<koreamap>")
2675
+ new_lines << line
2676
+ next
2677
+ end
2678
+
2679
+ processed = false
2680
+
2681
+ change_words.each do |change_word|
2682
+ # 1. [단어][주소] 패턴 처리: 분리 + 출력
2683
+ if line =~ /#{Regexp.escape(change_word)}\[(.*?)\]/
2684
+ match_data = line.match(/(.*)#{Regexp.escape(change_word)}\[(.*?)\](.*)/)
2685
+ if match_data
2686
+ before = match_data[1]
2687
+ address = match_data[2]
2688
+ after = match_data[3]
2689
+
2690
+ # 태그 추출
2691
+ open_tag = before[/<p[^>]*?>/i] || ""
2692
+ close_tag = after[/<\/p>/i] || ""
2693
+
2694
+ # 텍스트 정리
2695
+ before_text = before.sub(open_tag, '')
2696
+ after_text = after.sub(close_tag, '')
2697
+
2698
+ # 줄 분리
2699
+ new_lines << "#{open_tag}#{before_text}</p>" unless before_text.strip.empty?
2700
+ new_lines << "<koreamap>#{address}</koreamap>"
2701
+ new_lines << "#{open_tag}#{after_text}#{close_tag}" unless after_text.strip.empty?
2702
+
2703
+ processed = true
2704
+ break
2705
+ end
2706
+ end
2707
+
2708
+ # 2. 일반 단어 처리 (한 줄에만 등장하는 경우)
2709
+ if !processed && line.include?(change_word)
2710
+ parts = line.split(change_word, 2)
2711
+ prefix = parts[0]
2712
+ suffix = parts[1]
2713
+
2714
+ open_tag = prefix[/<p[^>]*?>/i] || ""
2715
+ close_tag = suffix[/<\/p>/i] || ""
2716
+
2717
+ prefix_text = prefix.sub(open_tag, '')
2718
+ suffix_text = suffix.sub(close_tag, '')
2719
+
2720
+ new_lines << "#{open_tag}#{prefix_text}</p>" unless prefix_text.strip.empty?
2721
+ new_lines << "<koreamap>#{map_address}</koreamap>"
2722
+ new_lines << "#{open_tag}#{suffix_text}#{close_tag}" unless suffix_text.strip.empty?
2723
+
2724
+ processed = true
2725
+ break
2726
+ end
2727
+ end
2728
+
2729
+ # 변경이 없었으면 원래 줄 추가
2730
+ new_lines << line unless processed
2586
2731
  end
2587
- end
2732
+
2733
+ content = new_lines.join("\n")
2734
+ end
2588
2735
 
2589
2736
 
2590
2737
 
@@ -2598,15 +2745,18 @@ class Wordpress
2598
2745
  # content = content
2599
2746
  # soosick_1 = content_end
2600
2747
  #else
2601
- if @data['포스트설정']['gpt키워드'].checked?
2602
- if @data['포스트설정']['gpt상단'].checked?
2603
- content = content_end+"\n"+content+"\n"
2604
- else
2605
- content = content+"\n"+content_end+"\n"
2606
- end
2748
+ parts = content.split('(자동생성글)', 2)
2749
+ content_main = parts[0].strip
2750
+ content_end = parts[1].to_s.strip
2751
+
2752
+ if @data['포스트설정']['gpt키워드'].checked?
2753
+ if @data['포스트설정']['gpt상단'].checked?
2754
+ content = content_end + "\n" + content_main + "\n"
2607
2755
  else
2608
- content = content+"\n"+content_end+"\n"
2609
-
2756
+ content = content_main + "\n" + content_end + "\n"
2757
+ end
2758
+ else
2759
+ content = content_main + "\n" + content_end + "\n"
2610
2760
  end
2611
2761
 
2612
2762
 
@@ -3889,6 +4039,7 @@ class Wordpress
3889
4039
  @data['image_size'][2].checked = false
3890
4040
  @data['image_size'][3].checked = false
3891
4041
  @data['image_size'][4].checked = false
4042
+ @data['image_size'][5].checked = false
3892
4043
  end
3893
4044
  }
3894
4045
  }
@@ -3899,6 +4050,7 @@ class Wordpress
3899
4050
  @data['image_size'][2].checked = false
3900
4051
  @data['image_size'][3].checked = false
3901
4052
  @data['image_size'][4].checked = false
4053
+ @data['image_size'][5].checked = false
3902
4054
  end
3903
4055
  }
3904
4056
  }
@@ -3909,6 +4061,7 @@ class Wordpress
3909
4061
  @data['image_size'][0].checked = false
3910
4062
  @data['image_size'][3].checked = false
3911
4063
  @data['image_size'][4].checked = false
4064
+ @data['image_size'][5].checked = false
3912
4065
  end
3913
4066
  }
3914
4067
  }
@@ -3919,6 +4072,7 @@ class Wordpress
3919
4072
  @data['image_size'][2].checked = false
3920
4073
  @data['image_size'][0].checked = false
3921
4074
  @data['image_size'][4].checked = false
4075
+ @data['image_size'][5].checked = false
3922
4076
  end
3923
4077
  }
3924
4078
  }
@@ -3929,6 +4083,18 @@ class Wordpress
3929
4083
  @data['image_size'][2].checked = false
3930
4084
  @data['image_size'][3].checked = false
3931
4085
  @data['image_size'][0].checked = false
4086
+ @data['image_size'][5].checked = false
4087
+ end
4088
+ }
4089
+ }
4090
+ @data['image_size'][5] = checkbox('원본 px'){
4091
+ on_toggled{
4092
+ if @data['image_size'][5].checked?
4093
+ @data['image_size'][1].checked = false
4094
+ @data['image_size'][2].checked = false
4095
+ @data['image_size'][3].checked = false
4096
+ @data['image_size'][0].checked = false
4097
+ @data['image_size'][4].checked = false
3932
4098
  end
3933
4099
  }
3934
4100
  }
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tblog_zon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.37
4
+ version: 0.0.50
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-23 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: []