tblog_duopack 0.0.15 → 0.0.37

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 +490 -378
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ab2729b67db87a5b1d9268f6968c4de28eba57b41fdda147d5d9b2c03b1cfe4
4
- data.tar.gz: e36e07e10f0333114eaeba2ca469e402b5f474a0bd019626d3f1f88efd7045ef
3
+ metadata.gz: 1a1b0ef75c64d091e8224a4f7617c78c90df8a17c0a008942b8ce99d99fd0c89
4
+ data.tar.gz: 858eb135367f64e0cd028f3883ee873b4bb443b67f762485e6af749508a07ed0
5
5
  SHA512:
6
- metadata.gz: 982fe58395dbe2621433b294229131296c18ec1bf1913d3e0f032576cf06caa67eeca2e0620e4903e064d6b5b57359558ab794c6c5f12b7342eab4d388c782f6
7
- data.tar.gz: 11ee935187d53949d3e9b38fa2c112e87ce815980f5a215d9b7e0c94c45387fe88e965174b0b041d640cf77351e296820f9ea9885cadb6919c21eeee5a9e1a8c
6
+ metadata.gz: 787f8a9f2f72c86dfccb4a721916ec4881fb16f8b8ef431aff25e97513bd028b1b6d6c898b018c0ac7cdc1167d2fbb9facc893d09aff559b2fd652c7f277b47d
7
+ data.tar.gz: 587816d392ee1c14cd4ec2c6acbd6d7543598b8ab29c9a28d02513cd3883c1bcf5bdd232111395101e6af7467b197232d761201f465ed4298005a22509f2d282
data/lib/tblog_duopack.rb CHANGED
@@ -25,93 +25,107 @@ include Glimmer
25
25
 
26
26
 
27
27
  class Chat
28
- def initialize(api_key)
28
+ def initialize(api_key, gpt_keyword_prompt)
29
29
  @api_key = api_key
30
+ @gpt_keyword_prompt = gpt_keyword_prompt
30
31
  end
31
32
 
32
- def message2(keyword)
33
- url = 'https://api.openai.com/v1/chat/completions'
34
- h = {
35
- 'Content-Type' => 'application/json',
36
- 'Authorization' => 'Bearer ' + @api_key
37
- }
38
- d = {
39
- #'model' => 'gpt-3.5-turbo',
40
- 'model' => 'gpt-4',
41
- 'messages' => [{
42
- "role" => "assistant",
43
- "content" => keyword.to_s+" 소개하는 글을 1500자에서 2500자 사이로 만들어줘"
44
- }]
45
- }
46
- answer = ''
47
- begin
48
- req = HTTP.headers(h).post(url, :json => d)
49
- print(req.to_s)
50
- answer = JSON.parse(req.to_s)['choices'][0]['message']['content']
51
- rescue => e
52
- begin
53
- answer = JSON.parse(req.to_s)['choices'][0]['message']['message']
54
- rescue
33
+ def message(keyword)
34
+ puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'
55
35
 
36
+ # "키워드 기반 글 생성 중..." 메시지 출력 스레드
37
+ thread = Thread.new do
38
+ while true
39
+ print "▶"
40
+ sleep 3
56
41
  end
57
42
  end
58
43
 
59
-
60
- print('api return ==> ')
61
- puts(answer)
62
-
63
- return answer
64
- end
65
-
66
- def message(keyword)
67
- puts 'chat gpt ...'
68
44
  url = 'https://api.openai.com/v1/chat/completions'
69
- h = {
45
+ headers = {
70
46
  'Content-Type' => 'application/json',
71
47
  'Authorization' => 'Bearer ' + @api_key
72
48
  }
73
- d = {
74
- #'model' => 'gpt-3.5-turbo',
49
+
50
+ # 사용자로부터 받은 입력과 GPT 프롬프트의 토큰 수 계산
51
+ message_tokens = calculate_tokens(keyword) + calculate_tokens(@gpt_keyword_prompt)
52
+
53
+ # 8,192 토큰을 초과하지 않도록 최대 토큰 수를 설정
54
+ max_response_tokens = [8192 - message_tokens, 4000].min # 8,192 - 입력된 토큰 수, 4,000 이하로 설정
55
+
56
+ # 요청 데이터 설정
57
+ data = {
75
58
  'model' => 'gpt-4',
76
- 'messages' => [{
77
- "role" => "assistant",
78
- "content" => keyword.to_s+" 관련된 글을 1500자에서 2500자 사이로 만들어줘"
79
- }]
59
+ 'messages' => [
60
+ {
61
+ "role" => "assistant",
62
+ "content" => "#{keyword}\n#{@gpt_keyword_prompt}"
63
+ }
64
+ ],
65
+ 'max_tokens' => max_response_tokens # 최대 응답 토큰 설정
80
66
  }
67
+
68
+
69
+
81
70
  answer = ''
82
71
  begin
83
- req = HTTP.headers(h).post(url, :json => d)
84
- print(req.to_s)
85
- answer = JSON.parse(req.to_s)['choices'][0]['message']['content']
86
- rescue => e
87
- begin
88
- answer = JSON.parse(req.to_s)['choices'][0]['message']['message']
89
- rescue
72
+ req = HTTP.headers(headers).post(url, :json => data)
90
73
 
74
+ # 상태 코드 확인
75
+ if req.status != 200
76
+ raise "HTTP Error: #{req.status}, Response Body: #{req.body.to_s}"
91
77
  end
92
- end
93
- con = 0
94
- while con > 5
95
- answer = answer + message2(keyword)
96
- if answer.length > 2000
97
- break
78
+
79
+ # 응답 내용 출력 (디버깅용)
80
+ response = JSON.parse(req.to_s)
81
+
82
+
83
+ # 응답 데이터에서 안전하게 값 추출
84
+ if response['choices'] && response['choices'][0] && response['choices'][0]['message']
85
+ answer = response['choices'][0]['message']['content']
86
+ else
87
+ raise "Invalid API response format"
98
88
  end
99
- con += 1
89
+ rescue => e
90
+ # 오류 메시지 출력
91
+ puts "Error occurred: #{e.message}"
92
+ answer = "오류가 발생했습니다."
100
93
  end
101
94
 
102
- print('api return ==> ')
103
- puts(answer)
95
+ # "생성 중..." 메시지 출력 종료
96
+ thread.kill
104
97
 
98
+ # 결과 로그 출력
99
+ puts "Final API response ==> #{answer}"
105
100
  return answer
106
101
  end
102
+
103
+ def calculate_tokens(text)
104
+ # 간단한 방식으로 텍스트의 토큰 수 계산 (정확도는 다를 수 있음)
105
+ # OpenAI API는 1토큰이 대략 4글자 정도임
106
+ text.split(/\s+/).length # 간단한 단어 수로 계산
107
+ end
107
108
  end
108
109
 
110
+
111
+
112
+
113
+
109
114
  class Chat_title
110
- def initialize(api_key)
115
+ def initialize(api_key, gpt_title_prompt)
111
116
  @api_key = api_key
117
+ @gpt_title_prompt = gpt_title_prompt
112
118
  end
113
119
 
114
120
  def message(title)
121
+ puts 'Sending request to GPT...(제목 생성 중...)'
122
+ # "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
123
+ thread = Thread.new do
124
+ while true
125
+ print "▶"
126
+ sleep(3)
127
+ end
128
+ end
115
129
  url = 'https://api.openai.com/v1/chat/completions'
116
130
  headers = {
117
131
  'Content-Type' => 'application/json',
@@ -125,15 +139,15 @@ class Chat_title
125
139
  },
126
140
  {
127
141
  "role" => "user",
128
- "content" => "#{title}\n위 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘."
142
+ "content" => "#{@gpt_title_prompt}\n#{title}"
129
143
  }]
130
144
  }
131
145
 
132
146
  begin
133
147
  req = HTTP.headers(headers).post(url, json: data)
134
- puts "HTTP Status: #{req.status}" # 상태 코드 확인
148
+
135
149
  response = JSON.parse(req.body.to_s)
136
- puts "API Response: #{response}" # 전체 응답 출력
150
+
137
151
 
138
152
  if req.status == 429
139
153
  return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
@@ -141,11 +155,18 @@ class Chat_title
141
155
 
142
156
  # 응답 데이터에서 안전하게 값 추출
143
157
  answer = response.dig('choices', 0, 'message', 'content')
144
- answer ||= (title) # 응답이 없을 경우 기본 메시지 설정
158
+
159
+ # 따옴표 제거
160
+ answer = answer.gsub('"', '') if answer
161
+
162
+ answer ||= title # 응답이 없을 경우 기본 메시지 설정
145
163
  rescue => e
146
164
  puts "Error: #{e.message}"
147
165
  answer = "오류가 발생했습니다."
148
166
  end
167
+
168
+ # "생성 중..." 메시지 출력 종료
169
+ thread.kill
149
170
 
150
171
  puts 'API return ==> '
151
172
  puts answer
@@ -153,12 +174,23 @@ class Chat_title
153
174
  end
154
175
  end
155
176
 
177
+
156
178
  class Chat_content
157
- def initialize(api_key)
179
+ def initialize(api_key, gpt_content_prompt)
158
180
  @api_key = api_key
181
+ @gpt_content_prompt = gpt_content_prompt
159
182
  end
160
183
 
161
184
  def message(content)
185
+ puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'
186
+ puts 'Sending request to GPT...(내용 변형 중...)'
187
+ # "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
188
+ thread = Thread.new do
189
+ while true
190
+ print "▶"
191
+ sleep(3)
192
+ end
193
+ end
162
194
 
163
195
  url = 'https://api.openai.com/v1/chat/completions'
164
196
  headers = {
@@ -173,15 +205,16 @@ class Chat_content
173
205
  },
174
206
  {
175
207
  "role" => "user",
176
- "content" => "#{content}\nChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해"
208
+ "content" => "#{@gpt_content_prompt}\n#{content}"
209
+
177
210
  }]
178
211
  }
179
212
 
180
213
  begin
181
214
  req = HTTP.headers(headers).post(url, json: data)
182
- puts "HTTP Status: #{req.status}" # 상태 코드 확인
215
+
183
216
  response = JSON.parse(req.body.to_s)
184
- puts "API Response: #{response}" # 전체 응답 출력
217
+
185
218
 
186
219
  if req.status == 429
187
220
  return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
@@ -195,6 +228,9 @@ class Chat_content
195
228
  answer = "오류가 발생했습니다."
196
229
  end
197
230
 
231
+ # "생성 중..." 메시지 출력 종료
232
+ thread.kill
233
+
198
234
  puts 'API return ==> '
199
235
  puts answer
200
236
  answer
@@ -202,6 +238,7 @@ class Chat_content
202
238
  end
203
239
 
204
240
 
241
+
205
242
  #############################################gpt############################################
206
243
 
207
244
  class Naver
@@ -214,7 +251,7 @@ class Naver
214
251
  # 공통 옵션 설정
215
252
  Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
216
253
  options = Selenium::WebDriver::Chrome::Options.new
217
-
254
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
218
255
  options.add_extension('./crx/app.crx') # 확장 프로그램을 첫 번째 탭에 추가
219
256
  options.add_argument('--disable-blink-features=AutomationControlled')
220
257
  options.add_argument('--disable-popup-blocking')
@@ -249,11 +286,14 @@ class Naver
249
286
 
250
287
  # 브라우저 실행
251
288
  begin
252
- # 드라이버 실행
253
- @driver = Selenium::WebDriver.for(:chrome, options: options)
254
-
255
- # 첫 번째 탭에서 확장 프로그램을 로드
256
- #@driver.get("chrome-extension://ifibfemgeogfhoebkmokieepdoobkbpo/options/options.html")
289
+ # 'capabilities'과 'options' 배열로 설정
290
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
291
+ capabilities["goog:chromeOptions"] = options.as_json
292
+
293
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
294
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
295
+
296
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
257
297
 
258
298
  sleep(1)
259
299
  # 두 번째 탭에서 로그인 페이지 열기
@@ -264,8 +304,15 @@ class Naver
264
304
 
265
305
  puts "Error: #{e.message}"
266
306
  puts 'Using default Chrome driver without proxy'
267
- @driver = Selenium::WebDriver.for(:chrome, options: options)
268
-
307
+ # 'capabilities'과 'options' 배열로 설정
308
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
309
+ capabilities["goog:chromeOptions"] = options.as_json
310
+
311
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
312
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
313
+
314
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
315
+
269
316
  # 첫 번째 탭에서 확장 프로그램을 로드
270
317
  #@driver.get("chrome-extension://ifibfemgeogfhoebkmokieepdoobkbpo/options/options.html")
271
318
  sleep(1)
@@ -1919,7 +1966,15 @@ class Wordpress
1919
1966
  end
1920
1967
 
1921
1968
  if @data['포스트설정']['gpt제목'].checked?
1922
- chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'))
1969
+ gpt_title_prompt = @data['포스트설정']['gpt제목_프롬프트'].text.to_s.force_encoding('utf-8')
1970
+
1971
+ # 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
1972
+ gpt_title_prompt_sample = gpt_title_prompt.strip.empty? ? "프롬프트: 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘." : gpt_title_prompt
1973
+
1974
+ # gpt_title_prompt_sample을 Chat_title 객체에 전달
1975
+ chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample)
1976
+
1977
+ # 메시지 요청 후 title에 저장
1923
1978
  gpt_text1 = chat.message(title)
1924
1979
  title = gpt_text1.to_s
1925
1980
  end
@@ -1964,18 +2019,16 @@ class Wordpress
1964
2019
  end
1965
2020
 
1966
2021
  if @data['포스트설정']['gpt내용'].checked?
2022
+ gpt_content_prompt = @data['포스트설정']['gpt내용_프롬프트'].text.to_s.force_encoding('utf-8')
1967
2023
  api_key = @data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8')
1968
- #key_change = @data['포스트설정']['특정단어키워드로변경값'].text.to_s.force_encoding('utf-8')
1969
- #imotcon_change = @data['포스트설정']['스티커로변경단어'].text.to_s.force_encoding('utf-8')
1970
- #template_change = @data['포스트설정']['내템플릿변경단어'].text.to_s.force_encoding('utf-8')
1971
- #ttdanar_change = @data['포스트설정']['단어링크적용단어'].text.to_s.force_encoding('utf-8')
1972
- #sajine_change = @data['포스트설정']['단어사진으로변경단어'].text.to_s.force_encoding('utf-8')
1973
- #mov_change = @data['포스트설정']['영상으로변경단어'].text.to_s.force_encoding('utf-8')
1974
- #map_change = @data['포스트설정']['지도로변경단어'].text.to_s.force_encoding('utf-8')
1975
- #inyong9_change = @data['포스트설정']['인용구변경단어'].text.to_s.force_encoding('utf-8')
1976
-
1977
2024
 
1978
- chat = Chat_content.new(api_key)
2025
+ # 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
2026
+ gpt_content_prompt_sample = gpt_content_prompt.strip.empty? ? "프롬프트:ChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해" : gpt_content_prompt
2027
+
2028
+ # Chat_content 객체 생성 시 api_key와 gpt_content_prompt_sample을 두 개의 인자로 전달
2029
+ chat = Chat_content.new(api_key, gpt_content_prompt_sample)
2030
+
2031
+ # 메시지 요청 후 content에 저장
1979
2032
  gpt_text3 = chat.message(content)
1980
2033
  content = gpt_text3.to_s
1981
2034
  end
@@ -2181,13 +2234,17 @@ class Wordpress
2181
2234
  @data['table'] << []
2182
2235
  @data['table'].pop
2183
2236
  if @data['포스트설정']['gpt키워드'].checked?
2184
- chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'))
2237
+ gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
2238
+ gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
2239
+ chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
2185
2240
  gpt_text = chat.message(keyword)
2186
- content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
2241
+ #content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
2242
+ content = content.to_s + "(자동생성글)" + gpt_text.to_s
2187
2243
  elsif @data['포스트설정']['내용을자동생성'].checked?
2188
2244
  content = auto_text
2189
2245
  elsif @data['포스트설정']['내용과자동생성'].checked?
2190
- content = content + "\n(자동생성글)\n" + auto_text
2246
+ #content = content + "\n(자동생성글)\n" + auto_text
2247
+ content = content + "(자동생성글)" + auto_text
2191
2248
  end
2192
2249
 
2193
2250
  if @data['포스트설정']['내용키워드삽입'].checked?
@@ -2222,7 +2279,8 @@ class Wordpress
2222
2279
  end
2223
2280
 
2224
2281
  if @data['포스트설정']['내용을자동생성'].checked?
2225
- content2 = content.split("\n")
2282
+ #content2 = content.split("\n")
2283
+ content2 = content.split
2226
2284
  end
2227
2285
 
2228
2286
  if @data['포스트설정']['내용과자동생성'].checked? or @data['포스트설정']['gpt키워드'].checked?
@@ -3199,162 +3257,170 @@ class Wordpress
3199
3257
  }
3200
3258
  }
3201
3259
  tab_item('내용설정'){
3260
+ horizontal_box{
3261
+ vertical_box{
3202
3262
  horizontal_box{
3203
- vertical_box{
3204
- horizontal_box{
3205
- stretchy false
3206
- button('키워드불러오기'){
3207
- on_clicked{
3208
- file = open_file
3209
- if file != nil
3210
- file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3211
- file_data.split("\n").each do |keyword|
3212
- if keyword.split(' ').join('').length < 2
3213
-
3214
- else
3215
- @data['키워드설정']['키워드'] << [false, keyword]
3216
- @data['키워드설정']['키워드'] << [false, keyword]
3217
- @data['키워드설정']['키워드'].pop
3218
- end
3219
- end
3220
- end
3221
-
3222
- }
3223
- }
3263
+ stretchy false
3264
+ button('키워드불러오기'){
3265
+ on_clicked{
3266
+ file = open_file
3267
+ if file != nil
3268
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3269
+ file_data.split("\n").each do |keyword|
3270
+ if keyword.split(' ').join('').length < 2
3224
3271
 
3225
- }
3226
- horizontal_box{
3227
- stretchy false
3228
- grid{
3229
- button('전체선택'){
3230
- top 1
3231
- left 1
3232
- on_clicked{
3233
- for n in 0..@data['키워드설정']['키워드'].length-1
3234
- @data['키워드설정']['키워드'][n][0] = true
3235
- @data['키워드설정']['키워드'] << []
3236
- @data['키워드설정']['키워드'].pop
3237
- end
3238
- }
3239
- }
3240
- button('선택해제'){
3241
- top 1
3242
- left 2
3243
- on_clicked{
3244
- for n in 0..@data['키워드설정']['키워드'].length-1
3245
- @data['키워드설정']['키워드'][n][0] = false
3246
- @data['키워드설정']['키워드'] << []
3272
+ else
3273
+ @data['키워드설정']['키워드'] << [false, keyword]
3274
+ @data['키워드설정']['키워드'] << [false, keyword]
3247
3275
  @data['키워드설정']['키워드'].pop
3248
3276
  end
3249
- }
3250
- }
3251
- button('삭제하기'){
3252
- top 1
3253
- left 3
3254
- on_clicked{
3255
- m = Array.new
3256
- for n in 0..@data['키워드설정']['키워드'].length-1
3257
- if @data['키워드설정']['키워드'][n][0] == true
3258
- m << n
3259
- end
3260
- end
3261
-
3262
- m.reverse.each do |i|
3263
- @data['키워드설정']['키워드'].delete_at(i)
3264
- end
3265
- @data['키워드설정']['키워드'].delete(nil)
3266
- }
3267
- }
3277
+ end
3278
+ end
3279
+
3268
3280
  }
3269
-
3270
- @data['키워드설정']['순서사용'] = checkbox('순서사용'){
3271
- stretchy false
3272
- on_toggled{ |c|
3273
- if c.checked?
3274
- @data['키워드설정']['랜덤사용'].checked = false
3275
- end
3276
- }
3277
- }
3278
- @data['키워드설정']['랜덤사용'] = checkbox('랜덤사용'){
3279
- stretchy false
3280
- on_toggled{ |c|
3281
- if c.checked?
3282
- @data['키워드설정']['순서사용'].checked = false
3283
- end
3284
- }
3285
- }
3281
+ }
3282
+
3283
+ }
3284
+ horizontal_box{
3285
+ stretchy false
3286
+ grid{
3287
+ button('전체선택'){
3288
+ top 1
3289
+ left 1
3290
+ on_clicked{
3291
+ for n in 0..@data['키워드설정']['키워드'].length-1
3292
+ @data['키워드설정']['키워드'][n][0] = true
3293
+ @data['키워드설정']['키워드'] << []
3294
+ @data['키워드설정']['키워드'].pop
3295
+ end
3286
3296
  }
3287
- vertical_separator{
3288
- stretchy false
3297
+ }
3298
+ button('선택해제'){
3299
+ top 1
3300
+ left 2
3301
+ on_clicked{
3302
+ for n in 0..@data['키워드설정']['키워드'].length-1
3303
+ @data['키워드설정']['키워드'][n][0] = false
3304
+ @data['키워드설정']['키워드'] << []
3305
+ @data['키워드설정']['키워드'].pop
3306
+ end
3289
3307
  }
3290
- horizontal_box{
3291
- stretchy false
3292
- grid{
3293
- @data['포스트설정']['gpt키워드'] = checkbox('GPT 키워드 기반 글 생성'){
3294
- top 1
3295
- left 0
3296
- #enabled false # 기본적으로 비활성화
3297
- on_toggled {
3298
- if @data['포스트설정']['gpt키워드'].checked?
3299
- @data['포스트설정']['gpt상단'].enabled = true # '내용투명' 활성화
3300
- @data['포스트설정']['gpt하단'].enabled = true # '내용투명' 활성화
3301
- else
3302
- @data['포스트설정']['gpt상단'].checked = false # 체크 해제
3303
- @data['포스트설정']['gpt상단'].enabled = false # 비활성화
3304
- @data['포스트설정']['gpt하단'].checked = false # 체크 해제
3305
- @data['포스트설정']['gpt하단'].enabled = false # 비활성화
3306
- end
3307
- }
3308
-
3309
- }
3310
-
3311
- @data['포스트설정']['gpt상단'] = checkbox('원고 위에 넣기'){
3312
- top 1
3313
- left 1
3314
- enabled false # 기본적으로 비활성화
3315
- on_toggled{
3316
- if @data['포스트설정']['gpt상단'].checked?
3317
- @data['포스트설정']['gpt하단'].checked = false
3318
- end
3319
- }
3320
- }
3321
-
3322
- @data['포스트설정']['gpt하단'] = checkbox('원고 아래 넣기'){
3323
- top 1
3324
- left 2
3325
- enabled false # 기본적으로 비활성화
3326
- on_toggled{
3327
- if @data['포스트설정']['gpt하단'].checked?
3328
- @data['포스트설정']['gpt상단'].checked = false
3308
+ }
3309
+ button('삭제하기'){
3310
+ top 1
3311
+ left 3
3312
+ on_clicked{
3313
+ m = Array.new
3314
+ for n in 0..@data['키워드설정']['키워드'].length-1
3315
+ if @data['키워드설정']['키워드'][n][0] == true
3316
+ m << n
3329
3317
  end
3330
- }
3331
- }
3332
- } }
3333
- horizontal_box{
3334
- stretchy false
3335
- grid{
3336
- label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3337
- } } }
3338
-
3339
- table{
3340
- checkbox_column('선택'){
3341
- editable true
3342
- }
3343
- text_column('키워드'){
3344
-
3345
- }
3318
+ end
3346
3319
 
3347
- cell_rows @data['키워드설정']['키워드']
3320
+ m.reverse.each do |i|
3321
+ @data['키워드설정']['키워드'].delete_at(i)
3322
+ end
3323
+ @data['키워드설정']['키워드'].delete(nil)
3348
3324
  }
3349
-
3350
3325
  }
3351
- vertical_separator{
3326
+ }
3327
+
3328
+ @data['키워드설정']['순서사용'] = checkbox('순서사용'){
3352
3329
  stretchy false
3330
+ on_toggled{ |c|
3331
+ if c.checked?
3332
+ @data['키워드설정']['랜덤사용'].checked = false
3333
+ end
3334
+ }
3353
3335
  }
3354
- vertical_box{
3355
- horizontal_box{
3356
- stretchy false
3357
- button('제목불러오기'){
3336
+ @data['키워드설정']['랜덤사용'] = checkbox('랜덤사용'){
3337
+ stretchy false
3338
+ on_toggled{ |c|
3339
+ if c.checked?
3340
+ @data['키워드설정']['순서사용'].checked = false
3341
+ end
3342
+ }
3343
+ }
3344
+ }
3345
+ vertical_separator{
3346
+ stretchy false
3347
+ }
3348
+ horizontal_box{
3349
+ stretchy false
3350
+ grid{
3351
+ @data['포스트설정']['gpt키워드'] = checkbox('GPT 키워드 기반 글 생성'){
3352
+ top 1
3353
+ left 0
3354
+ #enabled false # 기본적으로 비활성화
3355
+ on_toggled {
3356
+ if @data['포스트설정']['gpt키워드'].checked?
3357
+ @data['포스트설정']['gpt상단'].enabled = true # '내용투명' 활성화
3358
+ @data['포스트설정']['gpt하단'].enabled = true # '내용투명' 활성화
3359
+ else
3360
+ @data['포스트설정']['gpt상단'].checked = false # 체크 해제
3361
+ @data['포스트설정']['gpt상단'].enabled = false # 비활성화
3362
+ @data['포스트설정']['gpt하단'].checked = false # 체크 해제
3363
+ @data['포스트설정']['gpt하단'].enabled = false # 비활성화
3364
+ end
3365
+ }
3366
+
3367
+ }
3368
+
3369
+ @data['포스트설정']['gpt상단'] = checkbox('원고 위에 넣기'){
3370
+ top 1
3371
+ left 1
3372
+ enabled false # 기본적으로 비활성화
3373
+ on_toggled{
3374
+ if @data['포스트설정']['gpt상단'].checked?
3375
+ @data['포스트설정']['gpt하단'].checked = false
3376
+ end
3377
+ }
3378
+ }
3379
+
3380
+ @data['포스트설정']['gpt하단'] = checkbox('원고 아래 넣기'){
3381
+ top 1
3382
+ left 2
3383
+ enabled false # 기본적으로 비활성화
3384
+ on_toggled{
3385
+ if @data['포스트설정']['gpt하단'].checked?
3386
+ @data['포스트설정']['gpt상단'].checked = false
3387
+ end
3388
+ }
3389
+ }
3390
+ } }
3391
+ horizontal_box{
3392
+ stretchy false
3393
+ @data['포스트설정']['gpt키워드_프롬프트'] = entry(){
3394
+ text '프롬프트:관련 글을 1500자에서 2500자 사이로 만들어줘'
3395
+ }}
3396
+ horizontal_box{
3397
+ stretchy false
3398
+ grid{
3399
+ label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3400
+ } } }
3401
+
3402
+
3403
+ table{
3404
+ checkbox_column('선택'){
3405
+ editable true
3406
+ }
3407
+ text_column('키워드'){
3408
+
3409
+ }
3410
+
3411
+ cell_rows @data['키워드설정']['키워드']
3412
+ }
3413
+
3414
+
3415
+
3416
+ }
3417
+ vertical_separator{
3418
+ stretchy false
3419
+ }
3420
+ vertical_box{
3421
+ horizontal_box{
3422
+ stretchy false
3423
+ button('제목불러오기'){
3358
3424
  on_clicked{
3359
3425
  file = open_file
3360
3426
  if file != nil
@@ -3443,158 +3509,187 @@ class Wordpress
3443
3509
 
3444
3510
 
3445
3511
  }}}
3512
+ horizontal_box{
3513
+ stretchy false
3514
+ @data['포스트설정']['gpt제목_프롬프트'] = entry(){
3515
+ text '프롬프트:비슷한 길이로 제목으로 사용할수있게 하나만 만들어줘'
3516
+ }}
3446
3517
  horizontal_box{
3447
3518
  stretchy false
3448
3519
  grid{
3449
3520
  label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3450
3521
  } } }
3451
- table{
3452
- checkbox_column('선택'){
3453
- editable true
3454
- }
3455
- text_column('제목'){
3522
+
3456
3523
 
3457
- }
3524
+ table{
3525
+ checkbox_column('선택'){
3526
+ editable true
3527
+ }
3528
+ text_column('제목'){
3458
3529
 
3459
- cell_rows @data['제목설정']['제목']
3460
- }
3530
+ }
3531
+
3532
+ cell_rows @data['제목설정']['제목']
3533
+ }
3534
+
3461
3535
 
3536
+ }
3537
+ vertical_separator{
3538
+ stretchy false
3539
+ }
3540
+ vertical_box{
3541
+ horizontal_box{
3542
+ stretchy false
3543
+ button('내용불러오기'){
3544
+ on_clicked{
3545
+ file = open_file
3546
+ if file != nil
3547
+ file_name = file.split("\\")[-1]
3548
+ file_data = File.open(file,'r', :encoding => 'utf-8').read()
3549
+ if file_data.split("\n").length < 2
3550
+ file_data = file_data + "\n"
3551
+ end
3552
+ @data['내용설정']['내용'] << [false, file_name, file_data]
3553
+ @data['내용설정']['내용'] << [false, file_name, file_data]
3554
+ @data['내용설정']['내용'].pop
3555
+ end
3556
+ }
3462
3557
  }
3463
- vertical_separator{
3464
- stretchy false
3558
+
3559
+ }
3560
+ horizontal_box{
3561
+ stretchy false
3562
+ grid{
3563
+ button('전체선택'){
3564
+ top 1
3565
+ left 1
3566
+ on_clicked{
3567
+ for n in 0..@data['내용설정']['내용'].length-1
3568
+ @data['내용설정']['내용'][n][0] = true
3569
+ @data['내용설정']['내용'] << []
3570
+ @data['내용설정']['내용'].pop
3571
+ end
3572
+ }
3465
3573
  }
3466
- vertical_box{
3467
- horizontal_box{
3468
- stretchy false
3469
- button('내용불러오기'){
3470
- on_clicked{
3471
- file = open_file
3472
- if file != nil
3473
- file_name = file.split("\\")[-1]
3474
- file_data = File.open(file,'r', :encoding => 'utf-8').read()
3475
- if file_data.split("\n").length < 2
3476
- file_data = file_data + "\n"
3477
- end
3478
- @data['내용설정']['내용'] << [false, file_name, file_data]
3479
- @data['내용설정']['내용'] << [false, file_name, file_data]
3480
- @data['내용설정']['내용'].pop
3481
- end
3482
- }
3483
- }
3484
-
3574
+ button('선택해제'){
3575
+ top 1
3576
+ left 2
3577
+ on_clicked{
3578
+ for n in 0..@data['내용설정']['내용'].length-1
3579
+ @data['내용설정']['내용'][n][0] = false
3580
+ @data['내용설정']['내용'] << []
3581
+ @data['내용설정']['내용'].pop
3582
+ end
3485
3583
  }
3486
- horizontal_box{
3487
- stretchy false
3488
- grid{
3489
- button('전체선택'){
3490
- top 1
3491
- left 1
3492
- on_clicked{
3493
- for n in 0..@data['내용설정']['내용'].length-1
3494
- @data['내용설정']['내용'][n][0] = true
3495
- @data['내용설정']['내용'] << []
3496
- @data['내용설정']['내용'].pop
3497
- end
3498
- }
3499
- }
3500
- button('선택해제'){
3501
- top 1
3502
- left 2
3503
- on_clicked{
3504
- for n in 0..@data['내용설정']['내용'].length-1
3505
- @data['내용설정']['내용'][n][0] = false
3506
- @data['내용설정']['내용'] << []
3507
- @data['내용설정']['내용'].pop
3508
- end
3509
- }
3510
- }
3511
- button('삭제하기'){
3512
- top 1
3513
- left 3
3514
- on_clicked{
3515
- m = Array.new
3516
- for n in 0..@data['내용설정']['내용'].length-1
3517
- if @data['내용설정']['내용'][n][0] == true
3518
- m << n
3519
- end
3520
- end
3521
-
3522
- m.reverse.each do |i|
3523
- @data['내용설정']['내용'].delete_at(i)
3524
- end
3525
- @data['내용설정']['내용'].delete(nil)
3526
- }
3527
- }
3584
+ }
3585
+ button('삭제하기'){
3586
+ top 1
3587
+ left 3
3588
+ on_clicked{
3589
+ m = Array.new
3590
+ for n in 0..@data['내용설정']['내용'].length-1
3591
+ if @data['내용설정']['내용'][n][0] == true
3592
+ m << n
3593
+ end
3594
+ end
3595
+
3596
+ m.reverse.each do |i|
3597
+ @data['내용설정']['내용'].delete_at(i)
3598
+ end
3599
+ @data['내용설정']['내용'].delete(nil)
3528
3600
  }
3529
- @data['내용설정']['순서사용'] = checkbox('순서사용'){
3530
- stretchy false
3531
- on_toggled{ |c|
3532
- if c.checked?
3533
- @data['내용설정']['랜덤사용'].checked = false
3534
- end
3535
- }
3536
- }
3537
- @data['내용설정']['랜덤사용'] = checkbox('랜덤사용'){
3538
- stretchy false
3539
- on_toggled{ |c|
3540
- if c.checked?
3541
- @data['내용설정']['순서사용'].checked = false
3542
- end
3543
- }
3544
- }
3601
+ }
3602
+ }
3603
+ @data['내용설정']['순서사용'] = checkbox('순서사용'){
3604
+ stretchy false
3605
+ on_toggled{ |c|
3606
+ if c.checked?
3607
+ @data['내용설정']['랜덤사용'].checked = false
3608
+ end
3545
3609
  }
3546
- vertical_separator{
3547
- stretchy false
3610
+ }
3611
+ @data['내용설정']['랜덤사용'] = checkbox('랜덤사용'){
3612
+ stretchy false
3613
+ on_toggled{ |c|
3614
+ if c.checked?
3615
+ @data['내용설정']['순서사용'].checked = false
3616
+ end
3548
3617
  }
3549
- horizontal_box{
3550
- stretchy false
3551
- grid{
3552
- @data['포스트설정']['gpt내용'] = checkbox('내용파일을 이용해 GPT로 글 변형'){
3553
-
3554
-
3555
- }}}
3556
- horizontal_box{
3557
- stretchy false
3558
- grid{
3559
- label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3560
- } } }
3561
- table{
3562
- checkbox_column('선택'){
3563
- editable true
3564
- }
3565
- text_column('내용파일'){
3618
+ }
3619
+ }
3620
+ vertical_separator{
3621
+ stretchy false
3622
+ }
3623
+ horizontal_box{
3624
+ stretchy false
3625
+ grid{
3626
+ @data['포스트설정']['gpt내용'] = checkbox('내용파일을 이용해 GPT로 글 변형'){
3627
+
3628
+
3629
+ }}}
3630
+ horizontal_box{
3631
+ stretchy false
3632
+ @data['포스트설정']['gpt내용_프롬프트'] = entry(){
3633
+ text '프롬프트:동의어,유사어를 이용해 변경해줘'
3634
+ }}
3635
+ horizontal_box{
3636
+ stretchy false
3637
+ grid{
3638
+ label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3639
+ } } }
3640
+
3641
+ table{
3642
+ checkbox_column('선택'){
3643
+ editable true
3644
+ }
3645
+ text_column('내용파일'){
3566
3646
 
3567
- }
3647
+ }
3568
3648
 
3569
- cell_rows @data['내용설정']['내용']
3570
- }
3649
+ cell_rows @data['내용설정']['내용']
3650
+ }
3571
3651
 
3572
- horizontal_box{
3573
- stretchy false
3574
- @data['이미지설정']['폴더경로2'] = entry{
3575
- stretchy false
3576
- text "내용폴더경로 ex)C:\\내용\\폴더1"
3577
- }
3578
- button('폴더째로불러오기'){
3579
- stretchy false
3580
- on_clicked{
3581
- path = @data['이미지설정']['폴더경로2'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')
3582
- Dir.entries(@data['이미지설정']['폴더경로2'].text.to_s.force_encoding('utf-8')).each do |file|
3583
- if file == '.' or file == '..'
3652
+ horizontal_box{
3653
+ stretchy false
3654
+ @data['이미지설정']['폴더경로2'] = entry{
3655
+ stretchy false
3656
+ text "내용폴더경로 ex)C:\\내용\\폴더1"
3657
+ }
3584
3658
 
3585
- else
3586
- file_data = File.open(path+'/'+file,'r', :encoding => 'utf-8').read()
3659
+ button('폴더째로 불러오기') {
3660
+ on_clicked {
3661
+ path = @data['이미지설정']['폴더경로2'].text.to_s.force_encoding('utf-8')
3662
+
3663
+ # 경로가 유효한지 확인
3664
+ if Dir.exist?(path)
3665
+ Dir.entries(path).each do |file|
3666
+ if file == '.' or file == '..'
3667
+ next
3668
+ else
3669
+ begin
3670
+ # 파일을 열고 내용을 읽어서 추가
3671
+ file_data = File.open(path + '/' + file, 'r', encoding: 'utf-8').read
3587
3672
  @data['내용설정']['내용'] << [false, file, file_data]
3673
+ rescue => e
3674
+ # 파일을 열 수 없는 경우, 오류 메시지 출력
3675
+ puts "파일을 열 수 없습니다: #{file}, 오류: #{e.message}"
3588
3676
  end
3589
3677
  end
3590
- @data['내용설정']['내용'] << []
3591
- @data['내용설정']['내용'].pop
3592
- }
3593
- }
3678
+ end
3679
+
3680
+ # 내용 배열에서 마지막 빈 항목 제거
3681
+ @data['내용설정']['내용'] << []
3682
+ @data['내용설정']['내용'].pop
3683
+ else
3684
+ # 경로가 유효하지 않을 경우, 오류 메시지 출력
3685
+ puts "경로가 존재하지 않습니다: #{path}"
3686
+ end
3594
3687
  }
3595
3688
  }
3596
3689
  }
3597
3690
  }
3691
+ }
3692
+ }
3598
3693
  tab_item('이미지설정'){
3599
3694
  horizontal_box{
3600
3695
  vertical_box{
@@ -4056,36 +4151,53 @@ class Wordpress
4056
4151
  left 1
4057
4152
  text 'URL'
4058
4153
  }
4059
- @data['포스트설정']['내용을자동생성'] = checkbox('키워드기반 생성으로만 등록(GPT사용시 자체 생성)'){
4154
+ @data['포스트설정']['내용을자동생성'] = checkbox('키워드기반 글만 등록(GPT사용시 체크 해제)'){
4060
4155
  top 9
4061
4156
  left 0
4062
- on_toggled {
4063
- if @data['포스트설정']['내용을자동생성'].checked?
4064
- @data['포스트설정']['내용과자동생성'].checked = false
4065
- @data['포스트설정']['내용투명'].checked = false
4066
- @data['포스트설정']['내용투명'].enabled = false # 비활성화
4067
-
4068
- end
4157
+ on_toggled{
4158
+ if @data['포스트설정']['내용을자동생성'].checked?
4159
+ @data['포스트설정']['내용과자동생성'].checked = false
4160
+ @data['포스트설정']['내용투명'].checked = false
4161
+ @data['포스트설정']['내용투명'].enabled = false # 비활성화
4162
+
4163
+ end
4069
4164
  }
4070
4165
  }
4071
-
4072
-
4166
+ label('※GPT사용시 내용설정 탭에서 설정'){
4167
+ top 9
4168
+ left 1
4169
+ }
4170
+
4171
+ label('※GPT 미 사용시 세팅 권장'){
4172
+ top 9
4173
+ left 3
4174
+ }
4175
+
4176
+
4073
4177
  aa1 = 2
4074
- @data['포스트설정']['내용과자동생성'] = checkbox('내용파일+키워드기반 생성 등록(GPT사용시 자체 생성)') {
4178
+ @data['포스트설정']['내용과자동생성'] = checkbox('원고+키워드기반 등록(GPT사용시 체크 해제)') {
4075
4179
  top 10 + aa1
4076
4180
  left 0
4077
4181
  on_toggled {
4078
- if @data['포스트설정']['내용과자동생성'].checked?
4079
- @data['포스트설정']['내용을자동생성'].checked = false
4080
- @data['포스트설정']['내용투명'].enabled = true # '내용투명' 활성화
4081
-
4082
- else
4083
- @data['포스트설정']['내용투명'].checked = false # 체크 해제
4084
- @data['포스트설정']['내용투명'].enabled = false # 비활성화
4085
-
4086
- end
4182
+ if @data['포스트설정']['내용과자동생성'].checked?
4183
+ @data['포스트설정']['내용을자동생성'].checked = false
4184
+ @data['포스트설정']['내용투명'].enabled = true # '내용투명' 활성화
4185
+
4186
+ else
4187
+ @data['포스트설정']['내용투명'].checked = false # 체크 해제
4188
+ @data['포스트설정']['내용투명'].enabled = false # 비활성화
4189
+
4190
+ end
4087
4191
  }
4088
4192
  }
4193
+ label('※GPT사용시 내용설정 탭에서 설정'){
4194
+ top 10 + aa1
4195
+ left 1
4196
+ }
4197
+ label('※GPT 미 사용시 세팅 권장'){
4198
+ top 10 + aa1
4199
+ left 3
4200
+ }
4089
4201
 
4090
4202
  @data['포스트설정']['내용투명'] = checkbox('키워드 기반 자동 생성글 안보이게 처리') {
4091
4203
  top 11 + aa1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tblog_duopack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - zon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-20 00:00:00.000000000 Z
11
+ date: 2025-02-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: File to Clipboard gem
14
14
  email: mymin26@naver.com