cafe_basics_duo 0.1.50 → 0.1.52
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/cafe_basics_duo.rb +304 -150
- 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: 60647955187b2b942307988080314021176bf5359a4899611fd88293402edc38
|
4
|
+
data.tar.gz: 3d16d1ee3a8c39c168b031f4fcea42cf995981843523851f832b82f616d8e1ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb237f7fb35781a4e4f04d83b224ff6b22fece83cee9dec8c39fa3e01178b6a8db18e3e9dc9e4e14fd33d444740b1173fbdff9031228948b093de450cf1032d3
|
7
|
+
data.tar.gz: c06a8c8484d36289cab1c0efa7a5d1b1c557331c86a78e4539a92a1d89193c8034bfc6560753936109f364c6d5e82e654caf52cb7b523c2dd531f34c32fbcfcb
|
data/lib/cafe_basics_duo.rb
CHANGED
@@ -23,14 +23,16 @@ include AutoClickMethods
|
|
23
23
|
using Rainbow
|
24
24
|
include Glimmer
|
25
25
|
|
26
|
+
|
26
27
|
class Chat
|
27
|
-
def initialize(api_key, gpt_keyword_prompt)
|
28
|
+
def initialize(api_key, gpt_keyword_prompt, model)
|
28
29
|
@api_key = api_key
|
29
30
|
@gpt_keyword_prompt = gpt_keyword_prompt
|
31
|
+
@model = model # 모델을 인자로 받도록 수정
|
30
32
|
end
|
31
33
|
|
32
34
|
def message(keyword)
|
33
|
-
puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'
|
35
|
+
puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'.cyan
|
34
36
|
|
35
37
|
# "키워드 기반 글 생성 중..." 메시지 출력 스레드
|
36
38
|
thread = Thread.new do
|
@@ -54,7 +56,7 @@ class Chat
|
|
54
56
|
|
55
57
|
# 요청 데이터 설정
|
56
58
|
data = {
|
57
|
-
'model' =>
|
59
|
+
'model' => @model,
|
58
60
|
'messages' => [
|
59
61
|
{
|
60
62
|
"role" => "assistant",
|
@@ -64,9 +66,10 @@ class Chat
|
|
64
66
|
'max_tokens' => max_response_tokens # 최대 응답 토큰 설정
|
65
67
|
}
|
66
68
|
|
67
|
-
|
68
|
-
|
69
69
|
answer = ''
|
70
|
+
retry_count = 0
|
71
|
+
max_retries = 5 # 최대 재시도 횟수
|
72
|
+
|
70
73
|
begin
|
71
74
|
req = HTTP.headers(headers).post(url, :json => data)
|
72
75
|
|
@@ -77,7 +80,6 @@ class Chat
|
|
77
80
|
|
78
81
|
# 응답 내용 출력 (디버깅용)
|
79
82
|
response = JSON.parse(req.to_s)
|
80
|
-
|
81
83
|
|
82
84
|
# 응답 데이터에서 안전하게 값 추출
|
83
85
|
if response['choices'] && response['choices'][0] && response['choices'][0]['message']
|
@@ -88,14 +90,21 @@ class Chat
|
|
88
90
|
rescue => e
|
89
91
|
# 오류 메시지 출력
|
90
92
|
puts "Error occurred: #{e.message}"
|
91
|
-
|
93
|
+
if e.message.include?('502') && retry_count < max_retries
|
94
|
+
retry_count += 1
|
95
|
+
puts "Retrying... Attempt ##{retry_count}"
|
96
|
+
sleep(5) # 잠시 대기 후 재시도
|
97
|
+
retry
|
98
|
+
else
|
99
|
+
answer = "오류가 발생했습니다."
|
100
|
+
end
|
92
101
|
end
|
93
102
|
|
94
103
|
# "생성 중..." 메시지 출력 종료
|
95
104
|
thread.kill
|
96
105
|
|
97
106
|
# 결과 로그 출력
|
98
|
-
puts "Final API response ==> #{answer}"
|
107
|
+
puts "Final API response ==> #{answer}".cyan
|
99
108
|
return answer
|
100
109
|
end
|
101
110
|
|
@@ -108,16 +117,16 @@ end
|
|
108
117
|
|
109
118
|
|
110
119
|
|
111
|
-
|
112
|
-
|
113
120
|
class Chat_title
|
114
|
-
def initialize(api_key, gpt_title_prompt)
|
121
|
+
def initialize(api_key, gpt_title_prompt, model)
|
115
122
|
@api_key = api_key
|
116
123
|
@gpt_title_prompt = gpt_title_prompt
|
124
|
+
@model = model # 모델을 인자로 받도록 수정
|
117
125
|
end
|
118
126
|
|
119
127
|
def message(title)
|
120
|
-
puts 'Sending request to GPT...(제목 생성 중...)'
|
128
|
+
puts 'Sending request to GPT...(제목 생성 중...)'.cyan
|
129
|
+
|
121
130
|
# "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
|
122
131
|
thread = Thread.new do
|
123
132
|
while true
|
@@ -125,13 +134,15 @@ class Chat_title
|
|
125
134
|
sleep(3)
|
126
135
|
end
|
127
136
|
end
|
137
|
+
|
128
138
|
url = 'https://api.openai.com/v1/chat/completions'
|
129
139
|
headers = {
|
130
140
|
'Content-Type' => 'application/json',
|
131
141
|
'Authorization' => 'Bearer ' + @api_key
|
132
142
|
}
|
143
|
+
|
133
144
|
data = {
|
134
|
-
'model' =>
|
145
|
+
'model' => @model,
|
135
146
|
'messages' => [{
|
136
147
|
"role" => "system",
|
137
148
|
"content" => "너는 매우 친절하고 성의 있게 답변하는 AI 어시스턴트야."
|
@@ -142,11 +153,14 @@ class Chat_title
|
|
142
153
|
}]
|
143
154
|
}
|
144
155
|
|
156
|
+
answer = ''
|
157
|
+
retry_count = 0
|
158
|
+
max_retries = 5 # 최대 재시도 횟수
|
159
|
+
|
145
160
|
begin
|
146
161
|
req = HTTP.headers(headers).post(url, json: data)
|
147
162
|
|
148
163
|
response = JSON.parse(req.body.to_s)
|
149
|
-
|
150
164
|
|
151
165
|
if req.status == 429
|
152
166
|
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
@@ -161,28 +175,37 @@ class Chat_title
|
|
161
175
|
answer ||= title # 응답이 없을 경우 기본 메시지 설정
|
162
176
|
rescue => e
|
163
177
|
puts "Error: #{e.message}"
|
164
|
-
|
178
|
+
if e.message.include?('502') && retry_count < max_retries
|
179
|
+
retry_count += 1
|
180
|
+
puts "Retrying... Attempt ##{retry_count}"
|
181
|
+
sleep(5) # 잠시 대기 후 재시도
|
182
|
+
retry
|
183
|
+
else
|
184
|
+
answer = "오류가 발생했습니다."
|
185
|
+
end
|
165
186
|
end
|
166
187
|
|
167
188
|
# "생성 중..." 메시지 출력 종료
|
168
189
|
thread.kill
|
169
190
|
|
170
|
-
puts 'API return ==> '
|
171
|
-
puts answer
|
191
|
+
puts 'API return ==> '.cyan
|
192
|
+
puts answer.cyan
|
172
193
|
answer
|
173
194
|
end
|
174
195
|
end
|
175
196
|
|
176
197
|
|
177
198
|
class Chat_content
|
178
|
-
def initialize(api_key, gpt_content_prompt)
|
199
|
+
def initialize(api_key, gpt_content_prompt, model)
|
179
200
|
@api_key = api_key
|
180
201
|
@gpt_content_prompt = gpt_content_prompt
|
202
|
+
@model = model # 모델을 인자로 받도록 수정
|
181
203
|
end
|
182
204
|
|
183
205
|
def message(content)
|
184
|
-
puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'
|
185
|
-
puts 'Sending request to GPT...(내용 변형 중...)'
|
206
|
+
puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'.cyan
|
207
|
+
puts 'Sending request to GPT...(내용 변형 중...)'.cyan
|
208
|
+
|
186
209
|
# "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
|
187
210
|
thread = Thread.new do
|
188
211
|
while true
|
@@ -190,14 +213,15 @@ class Chat_content
|
|
190
213
|
sleep(3)
|
191
214
|
end
|
192
215
|
end
|
193
|
-
|
216
|
+
|
194
217
|
url = 'https://api.openai.com/v1/chat/completions'
|
195
218
|
headers = {
|
196
219
|
'Content-Type' => 'application/json',
|
197
220
|
'Authorization' => 'Bearer ' + @api_key
|
198
221
|
}
|
222
|
+
|
199
223
|
data = {
|
200
|
-
'model' =>
|
224
|
+
'model' => @model,
|
201
225
|
'messages' => [{
|
202
226
|
"role" => "system",
|
203
227
|
"content" => "너는 매우 친절하고 성의 있게 답변하는 AI 어시스턴트야."
|
@@ -205,16 +229,18 @@ class Chat_content
|
|
205
229
|
{
|
206
230
|
"role" => "user",
|
207
231
|
"content" => "#{@gpt_content_prompt}\n#{content}"
|
208
|
-
|
209
232
|
}]
|
210
233
|
}
|
211
234
|
|
235
|
+
answer = ''
|
236
|
+
retry_count = 0
|
237
|
+
max_retries = 5 # 최대 재시도 횟수
|
238
|
+
|
212
239
|
begin
|
213
240
|
req = HTTP.headers(headers).post(url, json: data)
|
214
241
|
|
215
242
|
response = JSON.parse(req.body.to_s)
|
216
|
-
|
217
|
-
|
243
|
+
|
218
244
|
if req.status == 429
|
219
245
|
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
220
246
|
end
|
@@ -224,14 +250,21 @@ class Chat_content
|
|
224
250
|
answer ||= (content) # 응답이 없을 경우 기본 메시지 설정
|
225
251
|
rescue => e
|
226
252
|
puts "Error: #{e.message}"
|
227
|
-
|
253
|
+
if e.message.include?('502') && retry_count < max_retries
|
254
|
+
retry_count += 1
|
255
|
+
puts "Retrying... Attempt ##{retry_count}"
|
256
|
+
sleep(5) # 잠시 대기 후 재시도
|
257
|
+
retry
|
258
|
+
else
|
259
|
+
answer = "오류가 발생했습니다."
|
260
|
+
end
|
228
261
|
end
|
229
262
|
|
230
263
|
# "생성 중..." 메시지 출력 종료
|
231
264
|
thread.kill
|
232
265
|
|
233
|
-
puts 'API return ==> '
|
234
|
-
puts answer
|
266
|
+
puts 'API return ==> '.cyan
|
267
|
+
puts answer.cyan
|
235
268
|
answer
|
236
269
|
end
|
237
270
|
end
|
@@ -2063,83 +2096,111 @@ class Wordpress
|
|
2063
2096
|
|
2064
2097
|
|
2065
2098
|
|
2066
|
-
def
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
client = HTTPClient.new
|
2071
|
-
client.default_header = {
|
2072
|
-
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
|
2073
|
-
'(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
|
2074
|
-
'Accept' => 'application/json, text/javascript, */*; q=0.01',
|
2075
|
-
'Accept-Language' => 'en-US,en;q=0.9',
|
2076
|
-
'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
|
2077
|
-
'X-Requested-With' => 'XMLHttpRequest'
|
2078
|
-
}
|
2099
|
+
def crop_image_height_under_width(path, min_crop_ratio = 0.625)
|
2100
|
+
img = Magick::Image.read(path).first
|
2101
|
+
width = img.columns
|
2102
|
+
height = img.rows
|
2079
2103
|
|
2080
|
-
retry_count = 0
|
2081
|
-
max_retries = 10
|
2082
|
-
results = []
|
2083
2104
|
|
2084
|
-
begin
|
2085
|
-
page = rand(1..15)
|
2086
|
-
url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
|
2087
|
-
puts "Request URL: #{url}"
|
2088
|
-
res = client.get(url)
|
2089
|
-
|
2090
|
-
unless res.status == 200
|
2091
|
-
puts "HTTP Error: #{res.status}"
|
2092
|
-
raise "HTTP Error"
|
2093
|
-
end
|
2094
2105
|
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2106
|
+
if height > width
|
2107
|
+
min_height = (width * min_crop_ratio).to_i
|
2108
|
+
new_height = rand(min_height..width)
|
2109
|
+
crop_top = ((height - new_height) / 2.0).round
|
2098
2110
|
|
2099
|
-
|
2100
|
-
|
2101
|
-
regular_url = photo.dig('urls', 'regular').to_s
|
2111
|
+
cropped = img.crop(0, crop_top, width, new_height, true)
|
2112
|
+
cropped.write(path)
|
2102
2113
|
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2106
|
-
|
2107
|
-
|
2114
|
+
|
2115
|
+
else
|
2116
|
+
|
2117
|
+
end
|
2118
|
+
end
|
2108
2119
|
|
2109
|
-
|
2110
|
-
|
2111
|
-
|
2120
|
+
def auto_image(keyword = nil)
|
2121
|
+
# auto_image 내부에서만 crop 호출
|
2122
|
+
keyword ||= @keyword
|
2123
|
+
puts "키워드: #{keyword}"
|
2124
|
+
|
2125
|
+
client = HTTPClient.new
|
2126
|
+
client.default_header = {
|
2127
|
+
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
|
2128
|
+
'(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
|
2129
|
+
'Accept' => 'application/json, text/javascript, */*; q=0.01',
|
2130
|
+
'Accept-Language' => 'en-US,en;q=0.9',
|
2131
|
+
'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
|
2132
|
+
'X-Requested-With' => 'XMLHttpRequest'
|
2133
|
+
}
|
2134
|
+
|
2135
|
+
retry_count = 0
|
2136
|
+
max_retries = 10
|
2137
|
+
results = []
|
2138
|
+
|
2139
|
+
begin
|
2140
|
+
page = rand(1..15)
|
2141
|
+
url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
|
2142
|
+
puts "Request URL: #{url}"
|
2143
|
+
res = client.get(url)
|
2144
|
+
|
2145
|
+
unless res.status == 200
|
2146
|
+
puts "HTTP Error: #{res.status}"
|
2147
|
+
raise "HTTP Error"
|
2148
|
+
end
|
2112
2149
|
|
2113
|
-
|
2114
|
-
|
2115
|
-
|
2150
|
+
json = JSON.parse(res.body)
|
2151
|
+
results = json['results']
|
2152
|
+
mm = []
|
2116
2153
|
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
2154
|
+
results.each do |photo|
|
2155
|
+
full_url = photo.dig('urls', 'full').to_s
|
2156
|
+
regular_url = photo.dig('urls', 'regular').to_s
|
2157
|
+
|
2158
|
+
if full_url.start_with?("https://images.unsplash.com/photo-") &&
|
2159
|
+
regular_url.include?("1080")
|
2160
|
+
mm << full_url
|
2161
|
+
end
|
2162
|
+
end
|
2163
|
+
|
2164
|
+
if mm.empty?
|
2165
|
+
raise "No matching image"
|
2166
|
+
end
|
2167
|
+
|
2168
|
+
selected_url = mm.sample
|
2169
|
+
destination_path = "./image/memory.png"
|
2170
|
+
Down.download(selected_url, destination: destination_path)
|
2171
|
+
puts "이미지 다운로드 완료: #{selected_url}"
|
2172
|
+
|
2173
|
+
# 오직 auto_image에서만 자르기 호출
|
2174
|
+
crop_image_height_under_width(destination_path)
|
2175
|
+
|
2176
|
+
rescue => e
|
2177
|
+
retry_count += 1
|
2178
|
+
puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
|
2179
|
+
sleep(3)
|
2180
|
+
if retry_count < max_retries
|
2181
|
+
retry
|
2182
|
+
else
|
2183
|
+
puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
|
2184
|
+
|
2185
|
+
if results && !results.empty?
|
2186
|
+
random_photo = results.sample
|
2187
|
+
fallback_url = random_photo.dig('urls', 'full')
|
2188
|
+
if fallback_url
|
2189
|
+
Down.download(fallback_url, destination: "./image/memory.png")
|
2190
|
+
puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
|
2191
|
+
crop_image_height_under_width("./image/memory.png")
|
2136
2192
|
else
|
2137
|
-
|
2138
|
-
|
2139
|
-
end
|
2193
|
+
puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
|
2194
|
+
color_image
|
2140
2195
|
end
|
2196
|
+
else
|
2197
|
+
puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
|
2198
|
+
color_image
|
2199
|
+
end
|
2141
2200
|
end
|
2142
2201
|
end
|
2202
|
+
end
|
2203
|
+
|
2143
2204
|
|
2144
2205
|
def color_image
|
2145
2206
|
color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
|
@@ -2233,57 +2294,104 @@ class Wordpress
|
|
2233
2294
|
end
|
2234
2295
|
|
2235
2296
|
|
2236
|
-
|
2297
|
+
def image_text(text1, text2)
|
2298
|
+
begin
|
2299
|
+
color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
|
2300
|
+
font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
|
2301
|
+
font2 = './fonts/' + font_files.sample
|
2302
|
+
|
2303
|
+
# 랜덤 글자색 선택
|
2304
|
+
color2 = color.sample
|
2305
|
+
|
2306
|
+
# 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
|
2307
|
+
def hex_to_rgb(hex)
|
2308
|
+
hex = hex.delete('#')
|
2309
|
+
[hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
|
2310
|
+
end
|
2311
|
+
|
2312
|
+
# 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
|
2313
|
+
def color_distance(c1, c2)
|
2314
|
+
Math.sqrt(
|
2315
|
+
(c1[0] - c2[0])**2 +
|
2316
|
+
(c1[1] - c2[1])**2 +
|
2317
|
+
(c1[2] - c2[2])**2
|
2318
|
+
)
|
2319
|
+
end
|
2320
|
+
|
2321
|
+
# 대비가 충분히 되는 테두리 색상 선택
|
2322
|
+
max_attempts = 10
|
2323
|
+
stroke_color = nil
|
2324
|
+
base_rgb = hex_to_rgb(color2)
|
2325
|
+
|
2326
|
+
max_attempts.times do
|
2327
|
+
candidate = color.sample
|
2328
|
+
candidate_rgb = hex_to_rgb(candidate)
|
2329
|
+
dist = color_distance(base_rgb, candidate_rgb)
|
2330
|
+
|
2331
|
+
# 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
|
2332
|
+
if dist > 100
|
2333
|
+
stroke_color = candidate
|
2334
|
+
break
|
2335
|
+
end
|
2336
|
+
end
|
2337
|
+
stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
|
2338
|
+
|
2339
|
+
img = Magick::Image.read('./image/memory.png').first
|
2340
|
+
draw = Magick::Draw.new
|
2341
|
+
|
2342
|
+
raw_message = "#{text1}\n#{text2}".strip
|
2343
|
+
max_width = img.columns * 0.85
|
2344
|
+
max_height = img.rows * 0.6
|
2345
|
+
|
2237
2346
|
begin
|
2238
|
-
|
2239
|
-
font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
|
2240
|
-
font2 = './fonts/' + font_files.sample
|
2241
|
-
color2 = color.sample
|
2242
|
-
|
2243
|
-
img = Magick::Image.read('./image/memory.png').first
|
2244
|
-
draw = Magick::Draw.new
|
2245
|
-
|
2246
|
-
raw_message = "#{text1}\n#{text2}".strip
|
2247
|
-
max_width = img.columns * 0.85
|
2248
|
-
max_height = img.rows * 0.6
|
2249
|
-
|
2250
|
-
begin
|
2251
|
-
size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
|
2252
|
-
rescue
|
2253
|
-
size = 30
|
2254
|
-
end
|
2255
|
-
|
2256
|
-
wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
|
2257
|
-
|
2258
|
-
if @data['이미지설정']['글자그림자'].checked?
|
2259
|
-
img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
|
2260
|
-
draw.gravity = Magick::CenterGravity
|
2261
|
-
draw.pointsize = adjusted_size
|
2262
|
-
draw.fill = '#000000'
|
2263
|
-
draw.font = font2
|
2264
|
-
end
|
2265
|
-
end
|
2266
|
-
|
2267
|
-
draw2 = Magick::Draw.new
|
2268
|
-
img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
|
2269
|
-
draw2.gravity = Magick::CenterGravity
|
2270
|
-
draw2.pointsize = adjusted_size
|
2271
|
-
draw2.fill = color2
|
2272
|
-
draw2.font = font2
|
2273
|
-
if @data['이미지설정']['글자테두리'].checked?
|
2274
|
-
draw2.stroke_width = 2
|
2275
|
-
draw2.stroke = '#000000'
|
2276
|
-
end
|
2277
|
-
end
|
2278
|
-
|
2279
|
-
img.write('./image/memory.png')
|
2347
|
+
size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
|
2280
2348
|
rescue
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2349
|
+
size = 30
|
2350
|
+
end
|
2351
|
+
|
2352
|
+
wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
|
2353
|
+
|
2354
|
+
if @data['이미지설정']['글자그림자'].checked?
|
2355
|
+
img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
|
2356
|
+
draw.gravity = Magick::CenterGravity
|
2357
|
+
draw.pointsize = adjusted_size
|
2358
|
+
draw.fill = '#000000'
|
2359
|
+
draw.font = font2
|
2360
|
+
end
|
2361
|
+
end
|
2362
|
+
|
2363
|
+
if @data['이미지설정']['글자테두리'].checked?
|
2364
|
+
draw_stroke = Magick::Draw.new
|
2365
|
+
img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
|
2366
|
+
draw_stroke.gravity = Magick::CenterGravity
|
2367
|
+
draw_stroke.pointsize = adjusted_size
|
2368
|
+
draw_stroke.fill = 'none'
|
2369
|
+
draw_stroke.stroke = stroke_color
|
2370
|
+
draw_stroke.stroke_width = rand(5..10)
|
2371
|
+
draw_stroke.font = font2
|
2372
|
+
end
|
2373
|
+
end
|
2374
|
+
|
2375
|
+
draw2 = Magick::Draw.new
|
2376
|
+
img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
|
2377
|
+
draw2.gravity = Magick::CenterGravity
|
2378
|
+
draw2.pointsize = adjusted_size
|
2379
|
+
draw2.fill = color2
|
2380
|
+
draw2.stroke = 'none'
|
2381
|
+
draw2.font = font2
|
2284
2382
|
end
|
2383
|
+
|
2384
|
+
img.write('./image/memory.png')
|
2385
|
+
|
2386
|
+
rescue => e
|
2387
|
+
puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
|
2388
|
+
sleep(3)
|
2389
|
+
retry
|
2390
|
+
end
|
2285
2391
|
end
|
2286
2392
|
|
2393
|
+
|
2394
|
+
|
2287
2395
|
def border()
|
2288
2396
|
color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
|
2289
2397
|
img = Magick::Image.read('./image/memory.png').first
|
@@ -2565,6 +2673,19 @@ class Wordpress
|
|
2565
2673
|
end
|
2566
2674
|
end
|
2567
2675
|
|
2676
|
+
if @data['포스트설정']['gpt35'].checked? || @data['포스트설정']['gpt4turbo'].checked? || @data['포스트설정']['gpt4'].checked?
|
2677
|
+
gpt_model = if @data['포스트설정']['gpt35'].checked?
|
2678
|
+
'gpt-3.5-turbo'
|
2679
|
+
elsif @data['포스트설정']['gpt4turbo'].checked?
|
2680
|
+
'gpt-4-turbo'
|
2681
|
+
elsif @data['포스트설정']['gpt4'].checked?
|
2682
|
+
'gpt-4'
|
2683
|
+
end
|
2684
|
+
puts "선택 된 GPT model: #{gpt_model}".green
|
2685
|
+
else
|
2686
|
+
|
2687
|
+
end
|
2688
|
+
|
2568
2689
|
if @data['포스트설정']['gpt제목'].checked?
|
2569
2690
|
gpt_title_prompt = @data['포스트설정']['gpt제목_프롬프트'].text.to_s.force_encoding('utf-8')
|
2570
2691
|
|
@@ -2572,7 +2693,7 @@ class Wordpress
|
|
2572
2693
|
gpt_title_prompt_sample = gpt_title_prompt.strip.empty? ? "프롬프트: 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘." : gpt_title_prompt
|
2573
2694
|
|
2574
2695
|
# gpt_title_prompt_sample을 Chat_title 객체에 전달
|
2575
|
-
chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample)
|
2696
|
+
chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample, gpt_model)
|
2576
2697
|
|
2577
2698
|
# 메시지 요청 후 title에 저장
|
2578
2699
|
gpt_text1 = chat.message(title)
|
@@ -2626,7 +2747,7 @@ class Wordpress
|
|
2626
2747
|
gpt_content_prompt_sample = gpt_content_prompt.strip.empty? ? "프롬프트:ChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해" : gpt_content_prompt
|
2627
2748
|
|
2628
2749
|
# Chat_content 객체 생성 시 api_key와 gpt_content_prompt_sample을 두 개의 인자로 전달
|
2629
|
-
chat = Chat_content.new(api_key, gpt_content_prompt_sample)
|
2750
|
+
chat = Chat_content.new(api_key, gpt_content_prompt_sample, gpt_model)
|
2630
2751
|
|
2631
2752
|
# 메시지 요청 후 content에 저장
|
2632
2753
|
gpt_text3 = chat.message(content)
|
@@ -2774,7 +2895,7 @@ class Wordpress
|
|
2774
2895
|
if @data['포스트설정']['gpt키워드'].checked?
|
2775
2896
|
gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
|
2776
2897
|
gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
|
2777
|
-
chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
|
2898
|
+
chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt, gpt_model)
|
2778
2899
|
gpt_text = chat.message(keyword)
|
2779
2900
|
#content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
|
2780
2901
|
content = content.to_s + "(자동생성글)" + gpt_text.to_s
|
@@ -3603,7 +3724,7 @@ class Wordpress
|
|
3603
3724
|
@data['포스트설정']['프록시리스트'] = Array.new
|
3604
3725
|
@data['포스트설정']['인용구'] = Array.new
|
3605
3726
|
@user_login_ok = 4
|
3606
|
-
window('카페 일반 게시판 등록기', 800,
|
3727
|
+
window('카페 일반 게시판 등록기', 800, 610) {
|
3607
3728
|
margined true
|
3608
3729
|
|
3609
3730
|
vertical_box {
|
@@ -4806,7 +4927,7 @@ class Wordpress
|
|
4806
4927
|
stretchy false
|
4807
4928
|
grid{
|
4808
4929
|
stretchy false
|
4809
|
-
@data['포스트설정']['제목키워드변경'] = checkbox('제목에 특정 단어를
|
4930
|
+
@data['포스트설정']['제목키워드변경'] = checkbox('제목에 특정 단어를 키워드로 변경'){
|
4810
4931
|
top 0
|
4811
4932
|
left 0
|
4812
4933
|
|
@@ -5106,17 +5227,49 @@ class Wordpress
|
|
5106
5227
|
top 15+ aa1
|
5107
5228
|
left 0
|
5108
5229
|
}
|
5109
|
-
|
5110
|
-
|
5111
|
-
|
5230
|
+
}
|
5231
|
+
grid{
|
5232
|
+
stretchy false
|
5233
|
+
@data['포스트설정']['ChatGPT사용'] = checkbox('Chat GPT 사용하기 '){
|
5234
|
+
top 1
|
5112
5235
|
left 0
|
5113
5236
|
}
|
5114
|
-
|
5237
|
+
|
5115
5238
|
@data['포스트설정']['api_key'] = entry(){
|
5116
|
-
top
|
5239
|
+
top 1
|
5117
5240
|
left 1
|
5118
|
-
text 'api key 입력
|
5241
|
+
text 'api key 입력'
|
5119
5242
|
}
|
5243
|
+
@data['포스트설정']['gpt35'] = checkbox('GPT 3.5-turbo'){
|
5244
|
+
top 1
|
5245
|
+
left 2
|
5246
|
+
on_toggled {
|
5247
|
+
if @data['포스트설정']['gpt35'].checked?
|
5248
|
+
@data['포스트설정']['gpt4'].checked = false
|
5249
|
+
@data['포스트설정']['gpt4turbo'].checked = false
|
5250
|
+
end
|
5251
|
+
}
|
5252
|
+
}
|
5253
|
+
@data['포스트설정']['gpt4'] = checkbox('GPT 4'){
|
5254
|
+
top 1
|
5255
|
+
left 3
|
5256
|
+
on_toggled {
|
5257
|
+
if @data['포스트설정']['gpt4'].checked?
|
5258
|
+
@data['포스트설정']['gpt35'].checked = false
|
5259
|
+
@data['포스트설정']['gpt4turbo'].checked = false
|
5260
|
+
end
|
5261
|
+
}
|
5262
|
+
}
|
5263
|
+
@data['포스트설정']['gpt4turbo'] = checkbox('GPT 4-turbo'){
|
5264
|
+
top 1
|
5265
|
+
left 4
|
5266
|
+
on_toggled {
|
5267
|
+
if @data['포스트설정']['gpt4turbo'].checked?
|
5268
|
+
@data['포스트설정']['gpt35'].checked = false
|
5269
|
+
@data['포스트설정']['gpt4'].checked = false
|
5270
|
+
end
|
5271
|
+
}
|
5272
|
+
}
|
5120
5273
|
}
|
5121
5274
|
}
|
5122
5275
|
|
@@ -5628,6 +5781,7 @@ class Wordpress
|
|
5628
5781
|
@data['포스트설정']['CCL사용'].checked = false
|
5629
5782
|
@data['포스트설정']['인용구랜덤'].checked = true
|
5630
5783
|
@data['이미지설정']['글자순서'].checked = true
|
5784
|
+
@data['포스트설정']['gpt35'].checked = true
|
5631
5785
|
}.show
|
5632
5786
|
end
|
5633
5787
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cafe_basics_duo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.52
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zon
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-06-26 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: File to Clipboard gem
|
13
13
|
email: mymin26@naver.com
|