tblog_duopack 0.0.15 → 0.0.33

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 +491 -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: c2f27cbb2244157106fe1960abc0e33b43ca9df1da28ee0c0ddc47cfbf3346d5
4
+ data.tar.gz: 8fdf4164701e3f939fe38dfddf19d66f31541e52784b147b5f46597f4da9f058
5
5
  SHA512:
6
- metadata.gz: 982fe58395dbe2621433b294229131296c18ec1bf1913d3e0f032576cf06caa67eeca2e0620e4903e064d6b5b57359558ab794c6c5f12b7342eab4d388c782f6
7
- data.tar.gz: 11ee935187d53949d3e9b38fa2c112e87ce815980f5a215d9b7e0c94c45387fe88e965174b0b041d640cf77351e296820f9ea9885cadb6919c21eeee5a9e1a8c
6
+ metadata.gz: d3e29ff309b404eaa6f51ed300261f482856d68d636a4ab43cb2df7f47c3b59fd24888c1a3c142298c0b764f3d3007c58761a73f414f2f6307e4aba1ef7321d2
7
+ data.tar.gz: bc5fc5d68d9ac5484f7093cfb02b80375b36fdffaf8029d5628ad08c3396e5420d07dcfad22a18f24a90802a9705176ad47cfa6f6c00147139bf5f4ab485d818
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,8 @@ 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') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
255
+ options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
218
256
  options.add_extension('./crx/app.crx') # 확장 프로그램을 첫 번째 탭에 추가
219
257
  options.add_argument('--disable-blink-features=AutomationControlled')
220
258
  options.add_argument('--disable-popup-blocking')
@@ -249,11 +287,14 @@ class Naver
249
287
 
250
288
  # 브라우저 실행
251
289
  begin
252
- # 드라이버 실행
253
- @driver = Selenium::WebDriver.for(:chrome, options: options)
254
-
255
- # 첫 번째 탭에서 확장 프로그램을 로드
256
- #@driver.get("chrome-extension://ifibfemgeogfhoebkmokieepdoobkbpo/options/options.html")
290
+ # 'capabilities'과 'options' 배열로 설정
291
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
292
+ capabilities["goog:chromeOptions"] = options.as_json
293
+
294
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
295
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
296
+
297
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
257
298
 
258
299
  sleep(1)
259
300
  # 두 번째 탭에서 로그인 페이지 열기
@@ -264,8 +305,15 @@ class Naver
264
305
 
265
306
  puts "Error: #{e.message}"
266
307
  puts 'Using default Chrome driver without proxy'
267
- @driver = Selenium::WebDriver.for(:chrome, options: options)
268
-
308
+ # 'capabilities'과 'options' 배열로 설정
309
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
310
+ capabilities["goog:chromeOptions"] = options.as_json
311
+
312
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
313
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
314
+
315
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
316
+
269
317
  # 첫 번째 탭에서 확장 프로그램을 로드
270
318
  #@driver.get("chrome-extension://ifibfemgeogfhoebkmokieepdoobkbpo/options/options.html")
271
319
  sleep(1)
@@ -1919,7 +1967,15 @@ class Wordpress
1919
1967
  end
1920
1968
 
1921
1969
  if @data['포스트설정']['gpt제목'].checked?
1922
- chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'))
1970
+ gpt_title_prompt = @data['포스트설정']['gpt제목_프롬프트'].text.to_s.force_encoding('utf-8')
1971
+
1972
+ # 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
1973
+ gpt_title_prompt_sample = gpt_title_prompt.strip.empty? ? "프롬프트: 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘." : gpt_title_prompt
1974
+
1975
+ # gpt_title_prompt_sample을 Chat_title 객체에 전달
1976
+ chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample)
1977
+
1978
+ # 메시지 요청 후 title에 저장
1923
1979
  gpt_text1 = chat.message(title)
1924
1980
  title = gpt_text1.to_s
1925
1981
  end
@@ -1964,18 +2020,16 @@ class Wordpress
1964
2020
  end
1965
2021
 
1966
2022
  if @data['포스트설정']['gpt내용'].checked?
2023
+ gpt_content_prompt = @data['포스트설정']['gpt내용_프롬프트'].text.to_s.force_encoding('utf-8')
1967
2024
  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
2025
 
1978
- chat = Chat_content.new(api_key)
2026
+ # 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
2027
+ gpt_content_prompt_sample = gpt_content_prompt.strip.empty? ? "프롬프트:ChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해" : gpt_content_prompt
2028
+
2029
+ # Chat_content 객체 생성 시 api_key와 gpt_content_prompt_sample을 두 개의 인자로 전달
2030
+ chat = Chat_content.new(api_key, gpt_content_prompt_sample)
2031
+
2032
+ # 메시지 요청 후 content에 저장
1979
2033
  gpt_text3 = chat.message(content)
1980
2034
  content = gpt_text3.to_s
1981
2035
  end
@@ -2181,13 +2235,17 @@ class Wordpress
2181
2235
  @data['table'] << []
2182
2236
  @data['table'].pop
2183
2237
  if @data['포스트설정']['gpt키워드'].checked?
2184
- chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'))
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)
2185
2241
  gpt_text = chat.message(keyword)
2186
- content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
2242
+ #content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
2243
+ content = content.to_s + "(자동생성글)" + gpt_text.to_s
2187
2244
  elsif @data['포스트설정']['내용을자동생성'].checked?
2188
2245
  content = auto_text
2189
2246
  elsif @data['포스트설정']['내용과자동생성'].checked?
2190
- content = content + "\n(자동생성글)\n" + auto_text
2247
+ #content = content + "\n(자동생성글)\n" + auto_text
2248
+ content = content + "(자동생성글)" + auto_text
2191
2249
  end
2192
2250
 
2193
2251
  if @data['포스트설정']['내용키워드삽입'].checked?
@@ -2222,7 +2280,8 @@ class Wordpress
2222
2280
  end
2223
2281
 
2224
2282
  if @data['포스트설정']['내용을자동생성'].checked?
2225
- content2 = content.split("\n")
2283
+ #content2 = content.split("\n")
2284
+ content2 = content.split
2226
2285
  end
2227
2286
 
2228
2287
  if @data['포스트설정']['내용과자동생성'].checked? or @data['포스트설정']['gpt키워드'].checked?
@@ -3199,162 +3258,170 @@ class Wordpress
3199
3258
  }
3200
3259
  }
3201
3260
  tab_item('내용설정'){
3261
+ horizontal_box{
3262
+ vertical_box{
3202
3263
  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
- }
3264
+ stretchy false
3265
+ button('키워드불러오기'){
3266
+ on_clicked{
3267
+ file = open_file
3268
+ if file != nil
3269
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3270
+ file_data.split("\n").each do |keyword|
3271
+ if keyword.split(' ').join('').length < 2
3224
3272
 
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['키워드설정']['키워드'] << []
3273
+ else
3274
+ @data['키워드설정']['키워드'] << [false, keyword]
3275
+ @data['키워드설정']['키워드'] << [false, keyword]
3247
3276
  @data['키워드설정']['키워드'].pop
3248
3277
  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
- }
3278
+ end
3279
+ end
3280
+
3268
3281
  }
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
- }
3282
+ }
3283
+
3284
+ }
3285
+ horizontal_box{
3286
+ stretchy false
3287
+ grid{
3288
+ button('전체선택'){
3289
+ top 1
3290
+ left 1
3291
+ on_clicked{
3292
+ for n in 0..@data['키워드설정']['키워드'].length-1
3293
+ @data['키워드설정']['키워드'][n][0] = true
3294
+ @data['키워드설정']['키워드'] << []
3295
+ @data['키워드설정']['키워드'].pop
3296
+ end
3286
3297
  }
3287
- vertical_separator{
3288
- stretchy false
3298
+ }
3299
+ button('선택해제'){
3300
+ top 1
3301
+ left 2
3302
+ on_clicked{
3303
+ for n in 0..@data['키워드설정']['키워드'].length-1
3304
+ @data['키워드설정']['키워드'][n][0] = false
3305
+ @data['키워드설정']['키워드'] << []
3306
+ @data['키워드설정']['키워드'].pop
3307
+ end
3289
3308
  }
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
3309
+ }
3310
+ button('삭제하기'){
3311
+ top 1
3312
+ left 3
3313
+ on_clicked{
3314
+ m = Array.new
3315
+ for n in 0..@data['키워드설정']['키워드'].length-1
3316
+ if @data['키워드설정']['키워드'][n][0] == true
3317
+ m << n
3329
3318
  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
- }
3319
+ end
3346
3320
 
3347
- cell_rows @data['키워드설정']['키워드']
3321
+ m.reverse.each do |i|
3322
+ @data['키워드설정']['키워드'].delete_at(i)
3323
+ end
3324
+ @data['키워드설정']['키워드'].delete(nil)
3348
3325
  }
3349
-
3350
3326
  }
3351
- vertical_separator{
3327
+ }
3328
+
3329
+ @data['키워드설정']['순서사용'] = checkbox('순서사용'){
3352
3330
  stretchy false
3331
+ on_toggled{ |c|
3332
+ if c.checked?
3333
+ @data['키워드설정']['랜덤사용'].checked = false
3334
+ end
3335
+ }
3353
3336
  }
3354
- vertical_box{
3355
- horizontal_box{
3356
- stretchy false
3357
- button('제목불러오기'){
3337
+ @data['키워드설정']['랜덤사용'] = checkbox('랜덤사용'){
3338
+ stretchy false
3339
+ on_toggled{ |c|
3340
+ if c.checked?
3341
+ @data['키워드설정']['순서사용'].checked = false
3342
+ end
3343
+ }
3344
+ }
3345
+ }
3346
+ vertical_separator{
3347
+ stretchy false
3348
+ }
3349
+ horizontal_box{
3350
+ stretchy false
3351
+ grid{
3352
+ @data['포스트설정']['gpt키워드'] = checkbox('GPT 키워드 기반 글 생성'){
3353
+ top 1
3354
+ left 0
3355
+ #enabled false # 기본적으로 비활성화
3356
+ on_toggled {
3357
+ if @data['포스트설정']['gpt키워드'].checked?
3358
+ @data['포스트설정']['gpt상단'].enabled = true # '내용투명' 활성화
3359
+ @data['포스트설정']['gpt하단'].enabled = true # '내용투명' 활성화
3360
+ else
3361
+ @data['포스트설정']['gpt상단'].checked = false # 체크 해제
3362
+ @data['포스트설정']['gpt상단'].enabled = false # 비활성화
3363
+ @data['포스트설정']['gpt하단'].checked = false # 체크 해제
3364
+ @data['포스트설정']['gpt하단'].enabled = false # 비활성화
3365
+ end
3366
+ }
3367
+
3368
+ }
3369
+
3370
+ @data['포스트설정']['gpt상단'] = checkbox('원고 위에 넣기'){
3371
+ top 1
3372
+ left 1
3373
+ enabled false # 기본적으로 비활성화
3374
+ on_toggled{
3375
+ if @data['포스트설정']['gpt상단'].checked?
3376
+ @data['포스트설정']['gpt하단'].checked = false
3377
+ end
3378
+ }
3379
+ }
3380
+
3381
+ @data['포스트설정']['gpt하단'] = checkbox('원고 아래 넣기'){
3382
+ top 1
3383
+ left 2
3384
+ enabled false # 기본적으로 비활성화
3385
+ on_toggled{
3386
+ if @data['포스트설정']['gpt하단'].checked?
3387
+ @data['포스트설정']['gpt상단'].checked = false
3388
+ end
3389
+ }
3390
+ }
3391
+ } }
3392
+ horizontal_box{
3393
+ stretchy false
3394
+ @data['포스트설정']['gpt키워드_프롬프트'] = entry(){
3395
+ text '프롬프트:관련 글을 1500자에서 2500자 사이로 만들어줘'
3396
+ }}
3397
+ horizontal_box{
3398
+ stretchy false
3399
+ grid{
3400
+ label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3401
+ } } }
3402
+
3403
+
3404
+ table{
3405
+ checkbox_column('선택'){
3406
+ editable true
3407
+ }
3408
+ text_column('키워드'){
3409
+
3410
+ }
3411
+
3412
+ cell_rows @data['키워드설정']['키워드']
3413
+ }
3414
+
3415
+
3416
+
3417
+ }
3418
+ vertical_separator{
3419
+ stretchy false
3420
+ }
3421
+ vertical_box{
3422
+ horizontal_box{
3423
+ stretchy false
3424
+ button('제목불러오기'){
3358
3425
  on_clicked{
3359
3426
  file = open_file
3360
3427
  if file != nil
@@ -3443,158 +3510,187 @@ class Wordpress
3443
3510
 
3444
3511
 
3445
3512
  }}}
3513
+ horizontal_box{
3514
+ stretchy false
3515
+ @data['포스트설정']['gpt제목_프롬프트'] = entry(){
3516
+ text '프롬프트:비슷한 길이로 제목으로 사용할수있게 하나만 만들어줘'
3517
+ }}
3446
3518
  horizontal_box{
3447
3519
  stretchy false
3448
3520
  grid{
3449
3521
  label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3450
3522
  } } }
3451
- table{
3452
- checkbox_column('선택'){
3453
- editable true
3454
- }
3455
- text_column('제목'){
3523
+
3456
3524
 
3457
- }
3525
+ table{
3526
+ checkbox_column('선택'){
3527
+ editable true
3528
+ }
3529
+ text_column('제목'){
3458
3530
 
3459
- cell_rows @data['제목설정']['제목']
3460
- }
3531
+ }
3532
+
3533
+ cell_rows @data['제목설정']['제목']
3534
+ }
3535
+
3461
3536
 
3537
+ }
3538
+ vertical_separator{
3539
+ stretchy false
3540
+ }
3541
+ vertical_box{
3542
+ horizontal_box{
3543
+ stretchy false
3544
+ button('내용불러오기'){
3545
+ on_clicked{
3546
+ file = open_file
3547
+ if file != nil
3548
+ file_name = file.split("\\")[-1]
3549
+ file_data = File.open(file,'r', :encoding => 'utf-8').read()
3550
+ if file_data.split("\n").length < 2
3551
+ file_data = file_data + "\n"
3552
+ end
3553
+ @data['내용설정']['내용'] << [false, file_name, file_data]
3554
+ @data['내용설정']['내용'] << [false, file_name, file_data]
3555
+ @data['내용설정']['내용'].pop
3556
+ end
3557
+ }
3462
3558
  }
3463
- vertical_separator{
3464
- stretchy false
3559
+
3560
+ }
3561
+ horizontal_box{
3562
+ stretchy false
3563
+ grid{
3564
+ button('전체선택'){
3565
+ top 1
3566
+ left 1
3567
+ on_clicked{
3568
+ for n in 0..@data['내용설정']['내용'].length-1
3569
+ @data['내용설정']['내용'][n][0] = true
3570
+ @data['내용설정']['내용'] << []
3571
+ @data['내용설정']['내용'].pop
3572
+ end
3573
+ }
3465
3574
  }
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
-
3575
+ button('선택해제'){
3576
+ top 1
3577
+ left 2
3578
+ on_clicked{
3579
+ for n in 0..@data['내용설정']['내용'].length-1
3580
+ @data['내용설정']['내용'][n][0] = false
3581
+ @data['내용설정']['내용'] << []
3582
+ @data['내용설정']['내용'].pop
3583
+ end
3485
3584
  }
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
- }
3585
+ }
3586
+ button('삭제하기'){
3587
+ top 1
3588
+ left 3
3589
+ on_clicked{
3590
+ m = Array.new
3591
+ for n in 0..@data['내용설정']['내용'].length-1
3592
+ if @data['내용설정']['내용'][n][0] == true
3593
+ m << n
3594
+ end
3595
+ end
3596
+
3597
+ m.reverse.each do |i|
3598
+ @data['내용설정']['내용'].delete_at(i)
3599
+ end
3600
+ @data['내용설정']['내용'].delete(nil)
3528
3601
  }
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
- }
3602
+ }
3603
+ }
3604
+ @data['내용설정']['순서사용'] = checkbox('순서사용'){
3605
+ stretchy false
3606
+ on_toggled{ |c|
3607
+ if c.checked?
3608
+ @data['내용설정']['랜덤사용'].checked = false
3609
+ end
3545
3610
  }
3546
- vertical_separator{
3547
- stretchy false
3611
+ }
3612
+ @data['내용설정']['랜덤사용'] = checkbox('랜덤사용'){
3613
+ stretchy false
3614
+ on_toggled{ |c|
3615
+ if c.checked?
3616
+ @data['내용설정']['순서사용'].checked = false
3617
+ end
3548
3618
  }
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('내용파일'){
3619
+ }
3620
+ }
3621
+ vertical_separator{
3622
+ stretchy false
3623
+ }
3624
+ horizontal_box{
3625
+ stretchy false
3626
+ grid{
3627
+ @data['포스트설정']['gpt내용'] = checkbox('내용파일을 이용해 GPT로 글 변형'){
3628
+
3629
+
3630
+ }}}
3631
+ horizontal_box{
3632
+ stretchy false
3633
+ @data['포스트설정']['gpt내용_프롬프트'] = entry(){
3634
+ text '프롬프트:동의어,유사어를 이용해 변경해줘'
3635
+ }}
3636
+ horizontal_box{
3637
+ stretchy false
3638
+ grid{
3639
+ label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3640
+ } } }
3641
+
3642
+ table{
3643
+ checkbox_column('선택'){
3644
+ editable true
3645
+ }
3646
+ text_column('내용파일'){
3566
3647
 
3567
- }
3648
+ }
3568
3649
 
3569
- cell_rows @data['내용설정']['내용']
3570
- }
3650
+ cell_rows @data['내용설정']['내용']
3651
+ }
3571
3652
 
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 == '..'
3653
+ horizontal_box{
3654
+ stretchy false
3655
+ @data['이미지설정']['폴더경로2'] = entry{
3656
+ stretchy false
3657
+ text "내용폴더경로 ex)C:\\내용\\폴더1"
3658
+ }
3584
3659
 
3585
- else
3586
- file_data = File.open(path+'/'+file,'r', :encoding => 'utf-8').read()
3660
+ button('폴더째로 불러오기') {
3661
+ on_clicked {
3662
+ path = @data['이미지설정']['폴더경로2'].text.to_s.force_encoding('utf-8')
3663
+
3664
+ # 경로가 유효한지 확인
3665
+ if Dir.exist?(path)
3666
+ Dir.entries(path).each do |file|
3667
+ if file == '.' or file == '..'
3668
+ next
3669
+ else
3670
+ begin
3671
+ # 파일을 열고 내용을 읽어서 추가
3672
+ file_data = File.open(path + '/' + file, 'r', encoding: 'utf-8').read
3587
3673
  @data['내용설정']['내용'] << [false, file, file_data]
3674
+ rescue => e
3675
+ # 파일을 열 수 없는 경우, 오류 메시지 출력
3676
+ puts "파일을 열 수 없습니다: #{file}, 오류: #{e.message}"
3588
3677
  end
3589
3678
  end
3590
- @data['내용설정']['내용'] << []
3591
- @data['내용설정']['내용'].pop
3592
- }
3593
- }
3679
+ end
3680
+
3681
+ # 내용 배열에서 마지막 빈 항목 제거
3682
+ @data['내용설정']['내용'] << []
3683
+ @data['내용설정']['내용'].pop
3684
+ else
3685
+ # 경로가 유효하지 않을 경우, 오류 메시지 출력
3686
+ puts "경로가 존재하지 않습니다: #{path}"
3687
+ end
3594
3688
  }
3595
3689
  }
3596
3690
  }
3597
3691
  }
3692
+ }
3693
+ }
3598
3694
  tab_item('이미지설정'){
3599
3695
  horizontal_box{
3600
3696
  vertical_box{
@@ -4056,36 +4152,53 @@ class Wordpress
4056
4152
  left 1
4057
4153
  text 'URL'
4058
4154
  }
4059
- @data['포스트설정']['내용을자동생성'] = checkbox('키워드기반 생성으로만 등록(GPT사용시 자체 생성)'){
4155
+ @data['포스트설정']['내용을자동생성'] = checkbox('키워드기반 글만 등록(GPT사용시 체크 해제)'){
4060
4156
  top 9
4061
4157
  left 0
4062
- on_toggled {
4063
- if @data['포스트설정']['내용을자동생성'].checked?
4064
- @data['포스트설정']['내용과자동생성'].checked = false
4065
- @data['포스트설정']['내용투명'].checked = false
4066
- @data['포스트설정']['내용투명'].enabled = false # 비활성화
4067
-
4068
- end
4158
+ on_toggled{
4159
+ if @data['포스트설정']['내용을자동생성'].checked?
4160
+ @data['포스트설정']['내용과자동생성'].checked = false
4161
+ @data['포스트설정']['내용투명'].checked = false
4162
+ @data['포스트설정']['내용투명'].enabled = false # 비활성화
4163
+
4164
+ end
4069
4165
  }
4070
4166
  }
4071
-
4072
-
4167
+ label('※GPT사용시 내용설정 탭에서 설정'){
4168
+ top 9
4169
+ left 1
4170
+ }
4171
+
4172
+ label('※GPT 미 사용시 세팅 권장'){
4173
+ top 9
4174
+ left 3
4175
+ }
4176
+
4177
+
4073
4178
  aa1 = 2
4074
- @data['포스트설정']['내용과자동생성'] = checkbox('내용파일+키워드기반 생성 등록(GPT사용시 자체 생성)') {
4179
+ @data['포스트설정']['내용과자동생성'] = checkbox('원고+키워드기반 등록(GPT사용시 체크 해제)') {
4075
4180
  top 10 + aa1
4076
4181
  left 0
4077
4182
  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
4183
+ if @data['포스트설정']['내용과자동생성'].checked?
4184
+ @data['포스트설정']['내용을자동생성'].checked = false
4185
+ @data['포스트설정']['내용투명'].enabled = true # '내용투명' 활성화
4186
+
4187
+ else
4188
+ @data['포스트설정']['내용투명'].checked = false # 체크 해제
4189
+ @data['포스트설정']['내용투명'].enabled = false # 비활성화
4190
+
4191
+ end
4087
4192
  }
4088
4193
  }
4194
+ label('※GPT사용시 내용설정 탭에서 설정'){
4195
+ top 10 + aa1
4196
+ left 1
4197
+ }
4198
+ label('※GPT 미 사용시 세팅 권장'){
4199
+ top 10 + aa1
4200
+ left 3
4201
+ }
4089
4202
 
4090
4203
  @data['포스트설정']['내용투명'] = checkbox('키워드 기반 자동 생성글 안보이게 처리') {
4091
4204
  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.33
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