nblog_zon 111.119.999 → 111.120.002
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/nblog_zon.rb +353 -191
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 595965e5f3c7b1d69d7c74b60132fdf593929cdae756140076d27e752b293262
|
4
|
+
data.tar.gz: 120f11c6c018d9ce3f5c4fe0f6200cc26687343102895b9fea21d9d6b5051c64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98e94f6a657edf2483cb147d0685bf1f22e4778e4cd9cd25c78847e71e452dadc41b3ac39d3fffecd34a905808a5bf7bc8a6e74dafd21b2495588d0cf32d20a0
|
7
|
+
data.tar.gz: fd9770bbc34d96c45c3cadd0a452ef31317cdad42ba6dc2466ec47783fc79ce1cfcf4de0f6daefb0acd9af9a2020dc1ff14ffcda7caa5e0dfdb3bc5c787ceb40
|
data/lib/nblog_zon.rb
CHANGED
@@ -22,15 +22,15 @@ require 'httpclient'
|
|
22
22
|
include AutoClickMethods
|
23
23
|
using Rainbow
|
24
24
|
include Glimmer
|
25
|
-
|
26
25
|
class Chat
|
27
|
-
def initialize(api_key, gpt_keyword_prompt)
|
26
|
+
def initialize(api_key, gpt_keyword_prompt, model)
|
28
27
|
@api_key = api_key
|
29
28
|
@gpt_keyword_prompt = gpt_keyword_prompt
|
29
|
+
@model = model # 모델을 인자로 받도록 수정
|
30
30
|
end
|
31
31
|
|
32
32
|
def message(keyword)
|
33
|
-
puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'
|
33
|
+
puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'.cyan
|
34
34
|
|
35
35
|
# "키워드 기반 글 생성 중..." 메시지 출력 스레드
|
36
36
|
thread = Thread.new do
|
@@ -54,7 +54,7 @@ class Chat
|
|
54
54
|
|
55
55
|
# 요청 데이터 설정
|
56
56
|
data = {
|
57
|
-
'model' =>
|
57
|
+
'model' => @model,
|
58
58
|
'messages' => [
|
59
59
|
{
|
60
60
|
"role" => "assistant",
|
@@ -64,9 +64,10 @@ class Chat
|
|
64
64
|
'max_tokens' => max_response_tokens # 최대 응답 토큰 설정
|
65
65
|
}
|
66
66
|
|
67
|
-
|
68
|
-
|
69
67
|
answer = ''
|
68
|
+
retry_count = 0
|
69
|
+
max_retries = 5 # 최대 재시도 횟수
|
70
|
+
|
70
71
|
begin
|
71
72
|
req = HTTP.headers(headers).post(url, :json => data)
|
72
73
|
|
@@ -77,7 +78,6 @@ class Chat
|
|
77
78
|
|
78
79
|
# 응답 내용 출력 (디버깅용)
|
79
80
|
response = JSON.parse(req.to_s)
|
80
|
-
|
81
81
|
|
82
82
|
# 응답 데이터에서 안전하게 값 추출
|
83
83
|
if response['choices'] && response['choices'][0] && response['choices'][0]['message']
|
@@ -88,14 +88,21 @@ class Chat
|
|
88
88
|
rescue => e
|
89
89
|
# 오류 메시지 출력
|
90
90
|
puts "Error occurred: #{e.message}"
|
91
|
-
|
91
|
+
if e.message.include?('502') && retry_count < max_retries
|
92
|
+
retry_count += 1
|
93
|
+
puts "Retrying... Attempt ##{retry_count}"
|
94
|
+
sleep(5) # 잠시 대기 후 재시도
|
95
|
+
retry
|
96
|
+
else
|
97
|
+
answer = "오류가 발생했습니다."
|
98
|
+
end
|
92
99
|
end
|
93
100
|
|
94
101
|
# "생성 중..." 메시지 출력 종료
|
95
102
|
thread.kill
|
96
103
|
|
97
104
|
# 결과 로그 출력
|
98
|
-
puts "Final API response ==> #{answer}"
|
105
|
+
puts "Final API response ==> #{answer}".cyan
|
99
106
|
return answer
|
100
107
|
end
|
101
108
|
|
@@ -108,16 +115,16 @@ end
|
|
108
115
|
|
109
116
|
|
110
117
|
|
111
|
-
|
112
|
-
|
113
118
|
class Chat_title
|
114
|
-
def initialize(api_key, gpt_title_prompt)
|
119
|
+
def initialize(api_key, gpt_title_prompt, model)
|
115
120
|
@api_key = api_key
|
116
121
|
@gpt_title_prompt = gpt_title_prompt
|
122
|
+
@model = model # 모델을 인자로 받도록 수정
|
117
123
|
end
|
118
124
|
|
119
125
|
def message(title)
|
120
|
-
puts 'Sending request to GPT...(제목 생성 중...)'
|
126
|
+
puts 'Sending request to GPT...(제목 생성 중...)'.cyan
|
127
|
+
|
121
128
|
# "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
|
122
129
|
thread = Thread.new do
|
123
130
|
while true
|
@@ -125,13 +132,15 @@ class Chat_title
|
|
125
132
|
sleep(3)
|
126
133
|
end
|
127
134
|
end
|
135
|
+
|
128
136
|
url = 'https://api.openai.com/v1/chat/completions'
|
129
137
|
headers = {
|
130
138
|
'Content-Type' => 'application/json',
|
131
139
|
'Authorization' => 'Bearer ' + @api_key
|
132
140
|
}
|
141
|
+
|
133
142
|
data = {
|
134
|
-
'model' =>
|
143
|
+
'model' => @model,
|
135
144
|
'messages' => [{
|
136
145
|
"role" => "system",
|
137
146
|
"content" => "너는 매우 친절하고 성의 있게 답변하는 AI 어시스턴트야."
|
@@ -142,11 +151,14 @@ class Chat_title
|
|
142
151
|
}]
|
143
152
|
}
|
144
153
|
|
154
|
+
answer = ''
|
155
|
+
retry_count = 0
|
156
|
+
max_retries = 5 # 최대 재시도 횟수
|
157
|
+
|
145
158
|
begin
|
146
159
|
req = HTTP.headers(headers).post(url, json: data)
|
147
160
|
|
148
161
|
response = JSON.parse(req.body.to_s)
|
149
|
-
|
150
162
|
|
151
163
|
if req.status == 429
|
152
164
|
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
@@ -161,28 +173,37 @@ class Chat_title
|
|
161
173
|
answer ||= title # 응답이 없을 경우 기본 메시지 설정
|
162
174
|
rescue => e
|
163
175
|
puts "Error: #{e.message}"
|
164
|
-
|
176
|
+
if e.message.include?('502') && retry_count < max_retries
|
177
|
+
retry_count += 1
|
178
|
+
puts "Retrying... Attempt ##{retry_count}"
|
179
|
+
sleep(5) # 잠시 대기 후 재시도
|
180
|
+
retry
|
181
|
+
else
|
182
|
+
answer = "오류가 발생했습니다."
|
183
|
+
end
|
165
184
|
end
|
166
185
|
|
167
186
|
# "생성 중..." 메시지 출력 종료
|
168
187
|
thread.kill
|
169
188
|
|
170
|
-
puts 'API return ==> '
|
171
|
-
puts answer
|
189
|
+
puts 'API return ==> '.cyan
|
190
|
+
puts answer.cyan
|
172
191
|
answer
|
173
192
|
end
|
174
193
|
end
|
175
194
|
|
176
195
|
|
177
196
|
class Chat_content
|
178
|
-
def initialize(api_key, gpt_content_prompt)
|
197
|
+
def initialize(api_key, gpt_content_prompt, model)
|
179
198
|
@api_key = api_key
|
180
199
|
@gpt_content_prompt = gpt_content_prompt
|
200
|
+
@model = model # 모델을 인자로 받도록 수정
|
181
201
|
end
|
182
202
|
|
183
203
|
def message(content)
|
184
|
-
puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'
|
185
|
-
puts 'Sending request to GPT...(내용 변형 중...)'
|
204
|
+
puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'.cyan
|
205
|
+
puts 'Sending request to GPT...(내용 변형 중...)'.cyan
|
206
|
+
|
186
207
|
# "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
|
187
208
|
thread = Thread.new do
|
188
209
|
while true
|
@@ -190,14 +211,15 @@ class Chat_content
|
|
190
211
|
sleep(3)
|
191
212
|
end
|
192
213
|
end
|
193
|
-
|
214
|
+
|
194
215
|
url = 'https://api.openai.com/v1/chat/completions'
|
195
216
|
headers = {
|
196
217
|
'Content-Type' => 'application/json',
|
197
218
|
'Authorization' => 'Bearer ' + @api_key
|
198
219
|
}
|
220
|
+
|
199
221
|
data = {
|
200
|
-
'model' =>
|
222
|
+
'model' => @model,
|
201
223
|
'messages' => [{
|
202
224
|
"role" => "system",
|
203
225
|
"content" => "너는 매우 친절하고 성의 있게 답변하는 AI 어시스턴트야."
|
@@ -205,16 +227,18 @@ class Chat_content
|
|
205
227
|
{
|
206
228
|
"role" => "user",
|
207
229
|
"content" => "#{@gpt_content_prompt}\n#{content}"
|
208
|
-
|
209
230
|
}]
|
210
231
|
}
|
211
232
|
|
233
|
+
answer = ''
|
234
|
+
retry_count = 0
|
235
|
+
max_retries = 5 # 최대 재시도 횟수
|
236
|
+
|
212
237
|
begin
|
213
238
|
req = HTTP.headers(headers).post(url, json: data)
|
214
239
|
|
215
240
|
response = JSON.parse(req.body.to_s)
|
216
|
-
|
217
|
-
|
241
|
+
|
218
242
|
if req.status == 429
|
219
243
|
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
220
244
|
end
|
@@ -224,20 +248,26 @@ class Chat_content
|
|
224
248
|
answer ||= (content) # 응답이 없을 경우 기본 메시지 설정
|
225
249
|
rescue => e
|
226
250
|
puts "Error: #{e.message}"
|
227
|
-
|
251
|
+
if e.message.include?('502') && retry_count < max_retries
|
252
|
+
retry_count += 1
|
253
|
+
puts "Retrying... Attempt ##{retry_count}"
|
254
|
+
sleep(5) # 잠시 대기 후 재시도
|
255
|
+
retry
|
256
|
+
else
|
257
|
+
answer = "오류가 발생했습니다."
|
258
|
+
end
|
228
259
|
end
|
229
260
|
|
230
261
|
# "생성 중..." 메시지 출력 종료
|
231
262
|
thread.kill
|
232
263
|
|
233
|
-
puts 'API return ==> '
|
234
|
-
puts answer
|
264
|
+
puts 'API return ==> '.cyan
|
265
|
+
puts answer.cyan
|
235
266
|
answer
|
236
267
|
end
|
237
268
|
end
|
238
269
|
|
239
270
|
|
240
|
-
|
241
271
|
#############################################gpt############################################
|
242
272
|
|
243
273
|
class Naver
|
@@ -2210,84 +2240,112 @@ class Wordpress
|
|
2210
2240
|
return @data2
|
2211
2241
|
end
|
2212
2242
|
|
2213
|
-
def
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
client = HTTPClient.new
|
2218
|
-
client.default_header = {
|
2219
|
-
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
|
2220
|
-
'(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
|
2221
|
-
'Accept' => 'application/json, text/javascript, */*; q=0.01',
|
2222
|
-
'Accept-Language' => 'en-US,en;q=0.9',
|
2223
|
-
'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
|
2224
|
-
'X-Requested-With' => 'XMLHttpRequest'
|
2225
|
-
}
|
2243
|
+
def crop_image_height_under_width(path, min_crop_ratio = 0.625)
|
2244
|
+
img = Magick::Image.read(path).first
|
2245
|
+
width = img.columns
|
2246
|
+
height = img.rows
|
2226
2247
|
|
2227
|
-
retry_count = 0
|
2228
|
-
max_retries = 10
|
2229
|
-
results = []
|
2230
2248
|
|
2231
|
-
begin
|
2232
|
-
page = rand(1..15)
|
2233
|
-
url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
|
2234
|
-
puts "Request URL: #{url}"
|
2235
|
-
res = client.get(url)
|
2236
|
-
|
2237
|
-
unless res.status == 200
|
2238
|
-
puts "HTTP Error: #{res.status}"
|
2239
|
-
raise "HTTP Error"
|
2240
|
-
end
|
2241
2249
|
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2250
|
+
if height > width
|
2251
|
+
min_height = (width * min_crop_ratio).to_i
|
2252
|
+
new_height = rand(min_height..width)
|
2253
|
+
crop_top = ((height - new_height) / 2.0).round
|
2245
2254
|
|
2246
|
-
|
2247
|
-
|
2248
|
-
regular_url = photo.dig('urls', 'regular').to_s
|
2255
|
+
cropped = img.crop(0, crop_top, width, new_height, true)
|
2256
|
+
cropped.write(path)
|
2249
2257
|
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
|
2258
|
+
|
2259
|
+
else
|
2260
|
+
|
2261
|
+
end
|
2262
|
+
end
|
2255
2263
|
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2264
|
+
def auto_image(keyword = nil)
|
2265
|
+
# auto_image 내부에서만 crop 호출
|
2266
|
+
keyword ||= @keyword
|
2267
|
+
puts "키워드: #{keyword}"
|
2268
|
+
|
2269
|
+
client = HTTPClient.new
|
2270
|
+
client.default_header = {
|
2271
|
+
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
|
2272
|
+
'(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
|
2273
|
+
'Accept' => 'application/json, text/javascript, */*; q=0.01',
|
2274
|
+
'Accept-Language' => 'en-US,en;q=0.9',
|
2275
|
+
'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
|
2276
|
+
'X-Requested-With' => 'XMLHttpRequest'
|
2277
|
+
}
|
2278
|
+
|
2279
|
+
retry_count = 0
|
2280
|
+
max_retries = 10
|
2281
|
+
results = []
|
2282
|
+
|
2283
|
+
begin
|
2284
|
+
page = rand(1..15)
|
2285
|
+
url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
|
2286
|
+
puts "Request URL: #{url}"
|
2287
|
+
res = client.get(url)
|
2288
|
+
|
2289
|
+
unless res.status == 200
|
2290
|
+
puts "HTTP Error: #{res.status}"
|
2291
|
+
raise "HTTP Error"
|
2292
|
+
end
|
2259
2293
|
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2294
|
+
json = JSON.parse(res.body)
|
2295
|
+
results = json['results']
|
2296
|
+
mm = []
|
2263
2297
|
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
|
2270
|
-
|
2271
|
-
|
2272
|
-
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2298
|
+
results.each do |photo|
|
2299
|
+
full_url = photo.dig('urls', 'full').to_s
|
2300
|
+
regular_url = photo.dig('urls', 'regular').to_s
|
2301
|
+
|
2302
|
+
if full_url.start_with?("https://images.unsplash.com/photo-") &&
|
2303
|
+
regular_url.include?("1080")
|
2304
|
+
mm << full_url
|
2305
|
+
end
|
2306
|
+
end
|
2307
|
+
|
2308
|
+
if mm.empty?
|
2309
|
+
raise "No matching image"
|
2310
|
+
end
|
2311
|
+
|
2312
|
+
selected_url = mm.sample
|
2313
|
+
destination_path = "./image/memory.png"
|
2314
|
+
Down.download(selected_url, destination: destination_path)
|
2315
|
+
puts "이미지 다운로드 완료: #{selected_url}"
|
2316
|
+
|
2317
|
+
# 오직 auto_image에서만 자르기 호출
|
2318
|
+
crop_image_height_under_width(destination_path)
|
2319
|
+
|
2320
|
+
rescue => e
|
2321
|
+
retry_count += 1
|
2322
|
+
puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
|
2323
|
+
sleep(3)
|
2324
|
+
if retry_count < max_retries
|
2325
|
+
retry
|
2326
|
+
else
|
2327
|
+
puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
|
2328
|
+
|
2329
|
+
if results && !results.empty?
|
2330
|
+
random_photo = results.sample
|
2331
|
+
fallback_url = random_photo.dig('urls', 'full')
|
2332
|
+
if fallback_url
|
2333
|
+
Down.download(fallback_url, destination: "./image/memory.png")
|
2334
|
+
puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
|
2335
|
+
crop_image_height_under_width("./image/memory.png")
|
2283
2336
|
else
|
2284
|
-
|
2285
|
-
|
2286
|
-
end
|
2337
|
+
puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
|
2338
|
+
color_image
|
2287
2339
|
end
|
2340
|
+
else
|
2341
|
+
puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
|
2342
|
+
color_image
|
2288
2343
|
end
|
2344
|
+
end
|
2345
|
+
end
|
2289
2346
|
end
|
2290
2347
|
|
2348
|
+
|
2291
2349
|
def color_image
|
2292
2350
|
color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
|
2293
2351
|
image = Magick::Image.new(740, 740) { |k| k.background_color = color.sample }
|
@@ -2381,56 +2439,103 @@ class Wordpress
|
|
2381
2439
|
|
2382
2440
|
|
2383
2441
|
def image_text(text1, text2)
|
2442
|
+
begin
|
2443
|
+
color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
|
2444
|
+
font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
|
2445
|
+
font2 = './fonts/' + font_files.sample
|
2446
|
+
|
2447
|
+
# 랜덤 글자색 선택
|
2448
|
+
color2 = color.sample
|
2449
|
+
|
2450
|
+
# 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
|
2451
|
+
def hex_to_rgb(hex)
|
2452
|
+
hex = hex.delete('#')
|
2453
|
+
[hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
|
2454
|
+
end
|
2455
|
+
|
2456
|
+
# 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
|
2457
|
+
def color_distance(c1, c2)
|
2458
|
+
Math.sqrt(
|
2459
|
+
(c1[0] - c2[0])**2 +
|
2460
|
+
(c1[1] - c2[1])**2 +
|
2461
|
+
(c1[2] - c2[2])**2
|
2462
|
+
)
|
2463
|
+
end
|
2464
|
+
|
2465
|
+
# 대비가 충분히 되는 테두리 색상 선택
|
2466
|
+
max_attempts = 10
|
2467
|
+
stroke_color = nil
|
2468
|
+
base_rgb = hex_to_rgb(color2)
|
2469
|
+
|
2470
|
+
max_attempts.times do
|
2471
|
+
candidate = color.sample
|
2472
|
+
candidate_rgb = hex_to_rgb(candidate)
|
2473
|
+
dist = color_distance(base_rgb, candidate_rgb)
|
2474
|
+
|
2475
|
+
# 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
|
2476
|
+
if dist > 100
|
2477
|
+
stroke_color = candidate
|
2478
|
+
break
|
2479
|
+
end
|
2480
|
+
end
|
2481
|
+
stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
|
2482
|
+
|
2483
|
+
img = Magick::Image.read('./image/memory.png').first
|
2484
|
+
draw = Magick::Draw.new
|
2485
|
+
|
2486
|
+
raw_message = "#{text1}\n#{text2}".strip
|
2487
|
+
max_width = img.columns * 0.85
|
2488
|
+
max_height = img.rows * 0.6
|
2489
|
+
|
2384
2490
|
begin
|
2385
|
-
|
2386
|
-
font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
|
2387
|
-
font2 = './fonts/' + font_files.sample
|
2388
|
-
color2 = color.sample
|
2389
|
-
|
2390
|
-
img = Magick::Image.read('./image/memory.png').first
|
2391
|
-
draw = Magick::Draw.new
|
2392
|
-
|
2393
|
-
raw_message = "#{text1}\n#{text2}".strip
|
2394
|
-
max_width = img.columns * 0.85
|
2395
|
-
max_height = img.rows * 0.6
|
2396
|
-
|
2397
|
-
begin
|
2398
|
-
size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
|
2399
|
-
rescue
|
2400
|
-
size = 30
|
2401
|
-
end
|
2402
|
-
|
2403
|
-
wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
|
2404
|
-
|
2405
|
-
if @data['이미지설정']['글자그림자'].checked?
|
2406
|
-
img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
|
2407
|
-
draw.gravity = Magick::CenterGravity
|
2408
|
-
draw.pointsize = adjusted_size
|
2409
|
-
draw.fill = '#000000'
|
2410
|
-
draw.font = font2
|
2411
|
-
end
|
2412
|
-
end
|
2413
|
-
|
2414
|
-
draw2 = Magick::Draw.new
|
2415
|
-
img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
|
2416
|
-
draw2.gravity = Magick::CenterGravity
|
2417
|
-
draw2.pointsize = adjusted_size
|
2418
|
-
draw2.fill = color2
|
2419
|
-
draw2.font = font2
|
2420
|
-
if @data['이미지설정']['글자테두리'].checked?
|
2421
|
-
draw2.stroke_width = 2
|
2422
|
-
draw2.stroke = '#000000'
|
2423
|
-
end
|
2424
|
-
end
|
2425
|
-
|
2426
|
-
img.write('./image/memory.png')
|
2491
|
+
size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
|
2427
2492
|
rescue
|
2428
|
-
|
2429
|
-
|
2430
|
-
|
2493
|
+
size = 30
|
2494
|
+
end
|
2495
|
+
|
2496
|
+
wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
|
2497
|
+
|
2498
|
+
if @data['이미지설정']['글자그림자'].checked?
|
2499
|
+
img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
|
2500
|
+
draw.gravity = Magick::CenterGravity
|
2501
|
+
draw.pointsize = adjusted_size
|
2502
|
+
draw.fill = '#000000'
|
2503
|
+
draw.font = font2
|
2504
|
+
end
|
2431
2505
|
end
|
2506
|
+
|
2507
|
+
if @data['이미지설정']['글자테두리'].checked?
|
2508
|
+
draw_stroke = Magick::Draw.new
|
2509
|
+
img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
|
2510
|
+
draw_stroke.gravity = Magick::CenterGravity
|
2511
|
+
draw_stroke.pointsize = adjusted_size
|
2512
|
+
draw_stroke.fill = 'none'
|
2513
|
+
draw_stroke.stroke = stroke_color
|
2514
|
+
draw_stroke.stroke_width = rand(5..10)
|
2515
|
+
draw_stroke.font = font2
|
2516
|
+
end
|
2517
|
+
end
|
2518
|
+
|
2519
|
+
draw2 = Magick::Draw.new
|
2520
|
+
img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
|
2521
|
+
draw2.gravity = Magick::CenterGravity
|
2522
|
+
draw2.pointsize = adjusted_size
|
2523
|
+
draw2.fill = color2
|
2524
|
+
draw2.stroke = 'none'
|
2525
|
+
draw2.font = font2
|
2526
|
+
end
|
2527
|
+
|
2528
|
+
img.write('./image/memory.png')
|
2529
|
+
|
2530
|
+
rescue => e
|
2531
|
+
puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
|
2532
|
+
sleep(3)
|
2533
|
+
retry
|
2534
|
+
end
|
2432
2535
|
end
|
2433
2536
|
|
2537
|
+
|
2538
|
+
|
2434
2539
|
def border()
|
2435
2540
|
color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
|
2436
2541
|
img = Magick::Image.read('./image/memory.png').first
|
@@ -2727,6 +2832,19 @@ class Wordpress
|
|
2727
2832
|
end
|
2728
2833
|
end
|
2729
2834
|
|
2835
|
+
if @data['포스트설정']['gpt35'].checked? || @data['포스트설정']['gpt4turbo'].checked? || @data['포스트설정']['gpt4'].checked?
|
2836
|
+
gpt_model = if @data['포스트설정']['gpt35'].checked?
|
2837
|
+
'gpt-3.5-turbo'
|
2838
|
+
elsif @data['포스트설정']['gpt4turbo'].checked?
|
2839
|
+
'gpt-4-turbo'
|
2840
|
+
elsif @data['포스트설정']['gpt4'].checked?
|
2841
|
+
'gpt-4'
|
2842
|
+
end
|
2843
|
+
puts "선택 된 GPT model: #{gpt_model}".green
|
2844
|
+
else
|
2845
|
+
|
2846
|
+
end
|
2847
|
+
|
2730
2848
|
if @data['포스트설정']['gpt제목'].checked?
|
2731
2849
|
gpt_title_prompt = @data['포스트설정']['gpt제목_프롬프트'].text.to_s.force_encoding('utf-8')
|
2732
2850
|
|
@@ -2734,7 +2852,7 @@ class Wordpress
|
|
2734
2852
|
gpt_title_prompt_sample = gpt_title_prompt.strip.empty? ? "프롬프트: 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘." : gpt_title_prompt
|
2735
2853
|
|
2736
2854
|
# gpt_title_prompt_sample을 Chat_title 객체에 전달
|
2737
|
-
chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample)
|
2855
|
+
chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample, gpt_model)
|
2738
2856
|
|
2739
2857
|
# 메시지 요청 후 title에 저장
|
2740
2858
|
gpt_text1 = chat.message(title)
|
@@ -2790,7 +2908,7 @@ class Wordpress
|
|
2790
2908
|
gpt_content_prompt_sample = gpt_content_prompt.strip.empty? ? "프롬프트:ChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해" : gpt_content_prompt
|
2791
2909
|
|
2792
2910
|
# Chat_content 객체 생성 시 api_key와 gpt_content_prompt_sample을 두 개의 인자로 전달
|
2793
|
-
chat = Chat_content.new(api_key, gpt_content_prompt_sample)
|
2911
|
+
chat = Chat_content.new(api_key, gpt_content_prompt_sample, gpt_model)
|
2794
2912
|
|
2795
2913
|
# 메시지 요청 후 content에 저장
|
2796
2914
|
gpt_text3 = chat.message(content)
|
@@ -2938,7 +3056,7 @@ class Wordpress
|
|
2938
3056
|
if @data['포스트설정']['gpt키워드'].checked?
|
2939
3057
|
gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
|
2940
3058
|
gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
|
2941
|
-
chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
|
3059
|
+
chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt, gpt_model)
|
2942
3060
|
gpt_text = chat.message(keyword)
|
2943
3061
|
#content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
|
2944
3062
|
content = content.to_s + "(자동생성글)" + gpt_text.to_s
|
@@ -3871,7 +3989,7 @@ class Wordpress
|
|
3871
3989
|
@data['포스트설정']['프록시리스트'] = Array.new
|
3872
3990
|
@data['포스트설정']['인용구'] = Array.new
|
3873
3991
|
@user_login_ok = "1"
|
3874
|
-
window('N_BLOG POSTING', 800,
|
3992
|
+
window('N_BLOG POSTING', 800, 610) {
|
3875
3993
|
margined true
|
3876
3994
|
|
3877
3995
|
vertical_box {
|
@@ -4894,7 +5012,11 @@ class Wordpress
|
|
4894
5012
|
vertical_box{
|
4895
5013
|
horizontal_box{
|
4896
5014
|
stretchy false
|
4897
|
-
|
5015
|
+
grid{
|
5016
|
+
stretchy false
|
5017
|
+
@data['image_type'][0] = checkbox('저장 사진 사용 '){
|
5018
|
+
top 0
|
5019
|
+
left 0
|
4898
5020
|
on_toggled{
|
4899
5021
|
if @data['image_type'][0].checked?
|
4900
5022
|
@data['image_type'][1].checked = false
|
@@ -4902,7 +5024,9 @@ class Wordpress
|
|
4902
5024
|
end
|
4903
5025
|
}
|
4904
5026
|
}
|
4905
|
-
@data['image_type'][1] = checkbox('색상 사진 사용'){
|
5027
|
+
@data['image_type'][1] = checkbox('색상 사진 사용 '){
|
5028
|
+
top 0
|
5029
|
+
left 1
|
4906
5030
|
on_toggled{
|
4907
5031
|
if @data['image_type'][1].checked?
|
4908
5032
|
@data['image_type'][0].checked = false
|
@@ -4911,6 +5035,8 @@ class Wordpress
|
|
4911
5035
|
}
|
4912
5036
|
}
|
4913
5037
|
@data['image_type'][2] = checkbox('자동 다운로드 사진 사용'){
|
5038
|
+
top 0
|
5039
|
+
left 2
|
4914
5040
|
on_toggled{
|
4915
5041
|
if @data['image_type'][2].checked?
|
4916
5042
|
@data['image_type'][1].checked = false
|
@@ -4919,7 +5045,7 @@ class Wordpress
|
|
4919
5045
|
}
|
4920
5046
|
}
|
4921
5047
|
}
|
4922
|
-
|
5048
|
+
}
|
4923
5049
|
grid{
|
4924
5050
|
stretchy false
|
4925
5051
|
@data['이미지설정']['글자삽입1'] = checkbox('글자 삽입1'){
|
@@ -4997,8 +5123,12 @@ class Wordpress
|
|
4997
5123
|
top 1
|
4998
5124
|
left 6
|
4999
5125
|
}
|
5000
|
-
|
5001
|
-
|
5126
|
+
}
|
5127
|
+
|
5128
|
+
grid{
|
5129
|
+
stretchy false
|
5130
|
+
@data['이미지설정']['글자순서'] = checkbox('글자 리스트 순서 사용 '){
|
5131
|
+
top 1
|
5002
5132
|
left 0
|
5003
5133
|
on_toggled{
|
5004
5134
|
if @data['이미지설정']['글자순서'].checked?
|
@@ -5007,8 +5137,8 @@ class Wordpress
|
|
5007
5137
|
}
|
5008
5138
|
}
|
5009
5139
|
|
5010
|
-
@data['이미지설정']['글자랜덤'] = checkbox('글자 리스트
|
5011
|
-
top
|
5140
|
+
@data['이미지설정']['글자랜덤'] = checkbox('글자 리스트 랜덤 사용'){
|
5141
|
+
top 1
|
5012
5142
|
left 1
|
5013
5143
|
on_toggled{
|
5014
5144
|
if @data['이미지설정']['글자랜덤'].checked?
|
@@ -5016,32 +5146,38 @@ class Wordpress
|
|
5016
5146
|
end
|
5017
5147
|
}
|
5018
5148
|
}
|
5149
|
+
}
|
5019
5150
|
|
5020
5151
|
|
5021
|
-
|
5022
|
-
|
5023
|
-
|
5152
|
+
grid{
|
5153
|
+
stretchy false
|
5154
|
+
@data['이미지설정']['필터사용'] = checkbox('사진 필터 사용 [흑백,흐림,가우시안,,,등 랜덤] (※색상 사진 사용시 적용 불가)'){
|
5155
|
+
top 0
|
5156
|
+
left 0
|
5024
5157
|
}
|
5025
|
-
|
5026
|
-
|
5158
|
+
}
|
5159
|
+
grid{
|
5160
|
+
stretchy false
|
5161
|
+
@data['이미지설정']['테두리사용'] = checkbox('사진 테두리 적용하기 '){
|
5162
|
+
top 1
|
5027
5163
|
left 0
|
5028
5164
|
}
|
5029
5165
|
@data['이미지설정']['테두리크기1'] = entry{
|
5030
|
-
top
|
5166
|
+
top 1
|
5031
5167
|
left 2
|
5032
5168
|
text 'ex) 1'
|
5033
5169
|
}
|
5034
|
-
label('
|
5035
|
-
top
|
5170
|
+
label('px'){
|
5171
|
+
top 1
|
5036
5172
|
left 3
|
5037
5173
|
}
|
5038
5174
|
@data['이미지설정']['테두리크기2'] = entry{
|
5039
|
-
top
|
5175
|
+
top 1
|
5040
5176
|
left 4
|
5041
5177
|
text 'ex) 33'
|
5042
5178
|
}
|
5043
|
-
label('
|
5044
|
-
top
|
5179
|
+
label('px'){
|
5180
|
+
top 1
|
5045
5181
|
left 5
|
5046
5182
|
}
|
5047
5183
|
|
@@ -5200,7 +5336,7 @@ class Wordpress
|
|
5200
5336
|
stretchy false
|
5201
5337
|
grid{
|
5202
5338
|
stretchy false
|
5203
|
-
@data['포스트설정']['제목키워드변경'] = checkbox('제목에 특정 단어를
|
5339
|
+
@data['포스트설정']['제목키워드변경'] = checkbox('제목에 특정 단어를 키워드로 변경'){
|
5204
5340
|
top 0
|
5205
5341
|
left 0
|
5206
5342
|
|
@@ -5243,13 +5379,10 @@ class Wordpress
|
|
5243
5379
|
left 3
|
5244
5380
|
text '최대수량'
|
5245
5381
|
}
|
5246
|
-
|
5247
|
-
|
5248
|
-
left 2
|
5249
|
-
}
|
5250
|
-
@data['포스트설정']['제목앞'] = checkbox('제목에 키워드 삽입 제목 앞'){
|
5382
|
+
|
5383
|
+
@data['포스트설정']['제목앞'] = checkbox('제목에 키워드 삽입시 제목 앞에 붙이기'){
|
5251
5384
|
top 3
|
5252
|
-
left
|
5385
|
+
left 0
|
5253
5386
|
enabled false # 기본적으로 비활성화
|
5254
5387
|
on_toggled{
|
5255
5388
|
if @data['포스트설정']['제목앞'].checked? == true
|
@@ -5259,13 +5392,10 @@ class Wordpress
|
|
5259
5392
|
end
|
5260
5393
|
}
|
5261
5394
|
}
|
5262
|
-
|
5263
|
-
|
5264
|
-
|
5265
|
-
|
5266
|
-
@data['포스트설정']['제목뒤'] = checkbox('제목에 키워드 삽입 제목 뒤'){
|
5267
|
-
top 4
|
5268
|
-
left 3
|
5395
|
+
|
5396
|
+
@data['포스트설정']['제목뒤'] = checkbox('제목에 키워드시 삽입 제목 뒤에 붙이기'){
|
5397
|
+
top 3
|
5398
|
+
left 1
|
5269
5399
|
enabled false # 기본적으로 비활성화
|
5270
5400
|
on_toggled{
|
5271
5401
|
if @data['포스트설정']['제목뒤'].checked? == true
|
@@ -5479,34 +5609,65 @@ class Wordpress
|
|
5479
5609
|
text 'URL'
|
5480
5610
|
}
|
5481
5611
|
|
5482
|
-
@data['포스트설정']['ChatGPT사용'] = checkbox('Chat GPT 사용하기'){
|
5483
|
-
top 15+ aa1
|
5484
|
-
left 0
|
5485
|
-
}
|
5486
|
-
|
5487
|
-
@data['포스트설정']['api_key'] = entry(){
|
5488
|
-
top 15+ aa1
|
5489
|
-
left 1
|
5490
|
-
text 'api key 입력 필수!!'
|
5491
|
-
}
|
5492
|
-
|
5493
5612
|
@data['포스트설정']['클립적용'] = checkbox('클립 내용에 넣기'){
|
5494
|
-
top
|
5613
|
+
top 15+ aa1
|
5495
5614
|
left 0
|
5496
5615
|
}
|
5497
5616
|
|
5498
5617
|
@data['포스트설정']['클립단어'] = entry(){
|
5499
|
-
top
|
5618
|
+
top 15+ aa1
|
5500
5619
|
left 1
|
5501
5620
|
text '특정단어'
|
5502
5621
|
}
|
5503
5622
|
@data['포스트설정']['클립넘버'] = entry(){
|
5504
|
-
top
|
5623
|
+
top 15+ aa1
|
5505
5624
|
left 3
|
5506
5625
|
text '클립넘버 ex)1,2,3'
|
5507
5626
|
}
|
5508
|
-
|
5509
5627
|
}
|
5628
|
+
grid{
|
5629
|
+
stretchy false
|
5630
|
+
@data['포스트설정']['ChatGPT사용'] = checkbox('Chat GPT 사용하기 '){
|
5631
|
+
top 1
|
5632
|
+
left 0
|
5633
|
+
}
|
5634
|
+
|
5635
|
+
@data['포스트설정']['api_key'] = entry(){
|
5636
|
+
top 1
|
5637
|
+
left 1
|
5638
|
+
text 'api key 입력'
|
5639
|
+
}
|
5640
|
+
@data['포스트설정']['gpt35'] = checkbox('GPT 3.5-turbo'){
|
5641
|
+
top 1
|
5642
|
+
left 2
|
5643
|
+
on_toggled {
|
5644
|
+
if @data['포스트설정']['gpt35'].checked?
|
5645
|
+
@data['포스트설정']['gpt4'].checked = false
|
5646
|
+
@data['포스트설정']['gpt4turbo'].checked = false
|
5647
|
+
end
|
5648
|
+
}
|
5649
|
+
}
|
5650
|
+
@data['포스트설정']['gpt4'] = checkbox('GPT 4'){
|
5651
|
+
top 1
|
5652
|
+
left 3
|
5653
|
+
on_toggled {
|
5654
|
+
if @data['포스트설정']['gpt4'].checked?
|
5655
|
+
@data['포스트설정']['gpt35'].checked = false
|
5656
|
+
@data['포스트설정']['gpt4turbo'].checked = false
|
5657
|
+
end
|
5658
|
+
}
|
5659
|
+
}
|
5660
|
+
@data['포스트설정']['gpt4turbo'] = checkbox('GPT 4-turbo'){
|
5661
|
+
top 1
|
5662
|
+
left 4
|
5663
|
+
on_toggled {
|
5664
|
+
if @data['포스트설정']['gpt4turbo'].checked?
|
5665
|
+
@data['포스트설정']['gpt35'].checked = false
|
5666
|
+
@data['포스트설정']['gpt4'].checked = false
|
5667
|
+
end
|
5668
|
+
}
|
5669
|
+
}
|
5670
|
+
}
|
5510
5671
|
}
|
5511
5672
|
|
5512
5673
|
vertical_separator{
|
@@ -6046,6 +6207,7 @@ class Wordpress
|
|
6046
6207
|
@data['포스트설정']['발행기능'].checked = true
|
6047
6208
|
@data['포스트설정']['인용구랜덤'].checked = true
|
6048
6209
|
@data['이미지설정']['글자순서'].checked = true
|
6210
|
+
@data['포스트설정']['gpt35'].checked = true
|
6049
6211
|
}.show
|
6050
6212
|
end
|
6051
6213
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nblog_zon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 111.
|
4
|
+
version: 111.120.002
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zon
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-06-
|
10
|
+
date: 2025-06-26 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: File to Clipboard gem
|
13
13
|
email: rnjstnswp123@naver.com
|