cafe_basics_duo 0.0.55 → 0.0.57

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/cafe_basics_duo.rb +544 -470
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 228181735f059dfb018eceeec5bbdfd81cdf2c25afb572375d7716d808bcdec5
4
- data.tar.gz: 15ee97f0e0b3af2e2d0028ee7802e22e70aab0755ff09c3d35763db379e7b50a
3
+ metadata.gz: c27bef52165f76a872fd99567c0994b41e14e7b5fe5fd744e60aff6a9fa684a5
4
+ data.tar.gz: 0c1ff9f0e0f26624e4deb595343ed68cb2ac1267e8341969642e42e816a2c05e
5
5
  SHA512:
6
- metadata.gz: 7153dab75607adb9dce4ea58de6597ed6ace93254442311353c4cf168dfc3d41f103f258cd317ebc4831804fa5d4ca8d2e811f831d0a2aec0d1503b7e136795e
7
- data.tar.gz: 58f63d9fb4dc98d9fc0c6e405866a9cf677ac95cfc9b15767752dd24bcd6eefc6f6a211cacfede02f43860763c978ca38eaac9bcaf13c38d9196e951af8bea91
6
+ metadata.gz: 8063886c46501d412944913befb416f2096a5757705566d5c86d5bdefb2d0790573d125d9d0ddb034fb4e668f0e23c6c08ee333f6cef0c449f560ad0275d834e
7
+ data.tar.gz: c5f53f6a0b44aa3607c32501900f940ceae3e9fe81c24dde0c5c789b95ad7bc2c39218c95e765e02fe5246ba27f5cf553c329c384119379f39edefbbd6d02df2
@@ -22,97 +22,107 @@ using Rainbow
22
22
  include Glimmer
23
23
 
24
24
  class Chat
25
-
26
- def initialize(api_key)
25
+ def initialize(api_key, gpt_keyword_prompt)
27
26
  @api_key = api_key
27
+ @gpt_keyword_prompt = gpt_keyword_prompt
28
28
  end
29
29
 
30
- def message2(keyword)
31
- puts'[GPT] 키워드 기반 글을 생성 중입니다.......'.yellow
32
- url = 'https://api.openai.com/v1/chat/completions'
33
- h = {
34
- 'Content-Type' => 'application/json',
35
- 'Authorization' => 'Bearer ' + @api_key
36
- }
37
- d = {
38
- #'model' => 'gpt-3.5-turbo',
39
- 'model' => 'gpt-4',
40
- 'messages' => [{
41
- "role" => "assistant",
42
- "content" => keyword.to_s+" 소개하는 글을 1500자에서 2500자 사이로 만들어줘"
43
- }]
44
- }
45
- answer = ''
46
- begin
47
- req = HTTP.headers(h).post(url, :json => d)
48
- print(req.to_s)
49
- answer = JSON.parse(req.to_s)['choices'][0]['message']['content']
50
- rescue => e
51
- begin
52
- answer = JSON.parse(req.to_s)['choices'][0]['message']['message']
53
- rescue
30
+ def message(keyword)
31
+ puts 'Sending request to GPT...(키워드 기반 생성 중...)'
54
32
 
33
+ # "키워드 기반 글 생성 중..." 메시지 출력 스레드
34
+ thread = Thread.new do
35
+ while true
36
+ print "▶"
37
+ sleep 3
55
38
  end
56
39
  end
57
40
 
58
-
59
- print('api return ==> ')
60
- puts(answer)
61
-
62
- return answer
63
- end
64
-
65
- def message(keyword)
66
- puts 'chat gpt ...'
67
41
  url = 'https://api.openai.com/v1/chat/completions'
68
- h = {
42
+ headers = {
69
43
  'Content-Type' => 'application/json',
70
44
  'Authorization' => 'Bearer ' + @api_key
71
45
  }
72
- d = {
73
- #'model' => 'gpt-3.5-turbo',
46
+
47
+ # 사용자로부터 받은 입력과 GPT 프롬프트의 토큰 수 계산
48
+ message_tokens = calculate_tokens(keyword) + calculate_tokens(@gpt_keyword_prompt)
49
+
50
+ # 8,192 토큰을 초과하지 않도록 최대 토큰 수를 설정
51
+ max_response_tokens = [8192 - message_tokens, 4000].min # 8,192 - 입력된 토큰 수, 4,000 이하로 설정
52
+
53
+ # 요청 데이터 설정
54
+ data = {
74
55
  'model' => 'gpt-4',
75
- 'messages' => [{
76
- "role" => "assistant",
77
- "content" => keyword.to_s+" 관련된 글을 1500자에서 2500자 사이로 만들어줘"
78
- }]
56
+ 'messages' => [
57
+ {
58
+ "role" => "assistant",
59
+ "content" => "#{keyword}\n#{@gpt_keyword_prompt}"
60
+ }
61
+ ],
62
+ 'max_tokens' => max_response_tokens # 최대 응답 토큰 설정
79
63
  }
64
+
65
+
66
+
80
67
  answer = ''
81
68
  begin
82
- req = HTTP.headers(h).post(url, :json => d)
83
- print(req.to_s)
84
- answer = JSON.parse(req.to_s)['choices'][0]['message']['content']
85
- rescue => e
86
- begin
87
- answer = JSON.parse(req.to_s)['choices'][0]['message']['message']
88
- rescue
69
+ req = HTTP.headers(headers).post(url, :json => data)
89
70
 
71
+ # 상태 코드 확인
72
+ if req.status != 200
73
+ raise "HTTP Error: #{req.status}, Response Body: #{req.body.to_s}"
90
74
  end
91
- end
92
- con = 0
93
- while con > 5
94
- answer = answer + message2(keyword)
95
- if answer.length > 2000
96
- break
75
+
76
+ # 응답 내용 출력 (디버깅용)
77
+ response = JSON.parse(req.to_s)
78
+
79
+
80
+ # 응답 데이터에서 안전하게 값 추출
81
+ if response['choices'] && response['choices'][0] && response['choices'][0]['message']
82
+ answer = response['choices'][0]['message']['content']
83
+ else
84
+ raise "Invalid API response format"
97
85
  end
98
- con += 1
86
+ rescue => e
87
+ # 오류 메시지 출력
88
+ puts "Error occurred: #{e.message}"
89
+ answer = "오류가 발생했습니다."
99
90
  end
100
91
 
101
- print('api return ==> ')
102
- puts(answer)
92
+ # "생성 중..." 메시지 출력 종료
93
+ thread.kill
103
94
 
95
+ # 결과 로그 출력
96
+ puts "Final API response ==> #{answer}"
104
97
  return answer
105
98
  end
99
+
100
+ def calculate_tokens(text)
101
+ # 간단한 방식으로 텍스트의 토큰 수 계산 (정확도는 다를 수 있음)
102
+ # OpenAI API는 1토큰이 대략 4글자 정도임
103
+ text.split(/\s+/).length # 간단한 단어 수로 계산
104
+ end
106
105
  end
107
106
 
107
+
108
+
109
+
110
+
108
111
  class Chat_title
109
-
110
- def initialize(api_key)
112
+ def initialize(api_key, gpt_title_prompt)
111
113
  @api_key = api_key
114
+ @gpt_title_prompt = gpt_title_prompt
112
115
  end
113
116
 
114
117
  def message(title)
115
- puts'[GPT] 유사 제목을 생성 중입니다.......'.yellow
118
+ puts 'Sending request to GPT...(제목 생성 중...)'
119
+ # "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
120
+ thread = Thread.new do
121
+ while true
122
+ print "▶"
123
+ sleep(3)
124
+ end
125
+ end
116
126
  url = 'https://api.openai.com/v1/chat/completions'
117
127
  headers = {
118
128
  'Content-Type' => 'application/json',
@@ -126,15 +136,15 @@ class Chat_title
126
136
  },
127
137
  {
128
138
  "role" => "user",
129
- "content" => "#{title}\n위 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘."
139
+ "content" => "#{@gpt_title_prompt}\n#{title}"
130
140
  }]
131
141
  }
132
142
 
133
143
  begin
134
144
  req = HTTP.headers(headers).post(url, json: data)
135
- puts "HTTP Status: #{req.status}" # 상태 코드 확인
145
+
136
146
  response = JSON.parse(req.body.to_s)
137
- puts "API Response: #{response}" # 전체 응답 출력
147
+
138
148
 
139
149
  if req.status == 429
140
150
  return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
@@ -142,11 +152,18 @@ class Chat_title
142
152
 
143
153
  # 응답 데이터에서 안전하게 값 추출
144
154
  answer = response.dig('choices', 0, 'message', 'content')
145
- answer ||= (title) # 응답이 없을 경우 기본 메시지 설정
155
+
156
+ # 따옴표 제거
157
+ answer = answer.gsub('"', '') if answer
158
+
159
+ answer ||= title # 응답이 없을 경우 기본 메시지 설정
146
160
  rescue => e
147
161
  puts "Error: #{e.message}"
148
162
  answer = "오류가 발생했습니다."
149
163
  end
164
+
165
+ # "생성 중..." 메시지 출력 종료
166
+ thread.kill
150
167
 
151
168
  puts 'API return ==> '
152
169
  puts answer
@@ -154,14 +171,24 @@ class Chat_title
154
171
  end
155
172
  end
156
173
 
174
+
157
175
  class Chat_content
158
-
159
- def initialize(api_key)
176
+ def initialize(api_key, gpt_content_prompt)
160
177
  @api_key = api_key
178
+ @gpt_content_prompt = gpt_content_prompt
161
179
  end
162
180
 
163
181
  def message(content)
164
- puts'[GPT] 유사 내용을 생성 중입니다! 조금만 기다려주세요.......'.yellow
182
+ puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'
183
+ puts 'Sending request to GPT...(내용 변형 중...)'
184
+ # "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
185
+ thread = Thread.new do
186
+ while true
187
+ print "▶"
188
+ sleep(3)
189
+ end
190
+ end
191
+
165
192
  url = 'https://api.openai.com/v1/chat/completions'
166
193
  headers = {
167
194
  'Content-Type' => 'application/json',
@@ -175,15 +202,16 @@ class Chat_content
175
202
  },
176
203
  {
177
204
  "role" => "user",
178
- "content" => "#{content}\nChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해"
205
+ "content" => "#{@gpt_content_prompt}\n#{content}"
206
+
179
207
  }]
180
208
  }
181
209
 
182
210
  begin
183
211
  req = HTTP.headers(headers).post(url, json: data)
184
- puts "HTTP Status: #{req.status}" # 상태 코드 확인
212
+
185
213
  response = JSON.parse(req.body.to_s)
186
- puts "API Response: #{response}" # 전체 응답 출력
214
+
187
215
 
188
216
  if req.status == 429
189
217
  return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
@@ -197,6 +225,9 @@ class Chat_content
197
225
  answer = "오류가 발생했습니다."
198
226
  end
199
227
 
228
+ # "생성 중..." 메시지 출력 종료
229
+ thread.kill
230
+
200
231
  puts 'API return ==> '
201
232
  puts answer
202
233
  answer
@@ -204,6 +235,7 @@ class Chat_content
204
235
  end
205
236
 
206
237
 
238
+
207
239
  #############################################gpt############################################
208
240
 
209
241
  class Naver
@@ -2279,7 +2311,15 @@ class Wordpress
2279
2311
  end
2280
2312
 
2281
2313
  if @data['포스트설정']['gpt제목'].checked?
2282
- chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'))
2314
+ gpt_title_prompt = @data['포스트설정']['gpt제목_프롬프트'].text.to_s.force_encoding('utf-8')
2315
+
2316
+ # 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
2317
+ gpt_title_prompt_sample = gpt_title_prompt.strip.empty? ? "프롬프트: 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘." : gpt_title_prompt
2318
+
2319
+ # gpt_title_prompt_sample을 Chat_title 객체에 전달
2320
+ chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample)
2321
+
2322
+ # 메시지 요청 후 title에 저장
2283
2323
  gpt_text1 = chat.message(title)
2284
2324
  title = gpt_text1.to_s
2285
2325
  end
@@ -2324,18 +2364,16 @@ class Wordpress
2324
2364
 
2325
2365
 
2326
2366
  if @data['포스트설정']['gpt내용'].checked?
2367
+ gpt_content_prompt = @data['포스트설정']['gpt내용_프롬프트'].text.to_s.force_encoding('utf-8')
2327
2368
  api_key = @data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8')
2328
- #key_change = @data['포스트설정']['특정단어키워드로변경값'].text.to_s.force_encoding('utf-8')
2329
- #imotcon_change = @data['포스트설정']['스티커로변경단어'].text.to_s.force_encoding('utf-8')
2330
- #template_change = @data['포스트설정']['내템플릿변경단어'].text.to_s.force_encoding('utf-8')
2331
- #ttdanar_change = @data['포스트설정']['단어링크적용단어'].text.to_s.force_encoding('utf-8')
2332
- #sajine_change = @data['포스트설정']['단어사진으로변경단어'].text.to_s.force_encoding('utf-8')
2333
- #mov_change = @data['포스트설정']['영상으로변경단어'].text.to_s.force_encoding('utf-8')
2334
- #map_change = @data['포스트설정']['지도로변경단어'].text.to_s.force_encoding('utf-8')
2335
- #inyong9_change = @data['포스트설정']['인용구변경단어'].text.to_s.force_encoding('utf-8')
2336
-
2337
2369
 
2338
- chat = Chat_content.new(api_key)
2370
+ # 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
2371
+ gpt_content_prompt_sample = gpt_content_prompt.strip.empty? ? "프롬프트:ChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해" : gpt_content_prompt
2372
+
2373
+ # Chat_content 객체 생성 시 api_key와 gpt_content_prompt_sample을 두 개의 인자로 전달
2374
+ chat = Chat_content.new(api_key, gpt_content_prompt_sample)
2375
+
2376
+ # 메시지 요청 후 content에 저장
2339
2377
  gpt_text3 = chat.message(content)
2340
2378
  content = gpt_text3.to_s
2341
2379
  end
@@ -2539,13 +2577,17 @@ class Wordpress
2539
2577
  @data['table'] << []
2540
2578
  @data['table'].pop
2541
2579
  if @data['포스트설정']['gpt키워드'].checked?
2542
- chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'))
2580
+ gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
2581
+ gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
2582
+ chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
2543
2583
  gpt_text = chat.message(keyword)
2544
- content = content + "\n(자동생성글)\n" + gpt_text
2584
+ #content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
2585
+ content = content.to_s + "(자동생성글)" + gpt_text.to_s
2545
2586
  elsif @data['포스트설정']['내용을자동생성'].checked?
2546
2587
  content = auto_text
2547
2588
  elsif @data['포스트설정']['내용과자동생성'].checked?
2548
- content = content + "\n(자동생성글)\n" + auto_text
2589
+ #content = content + "\n(자동생성글)\n" + auto_text
2590
+ content = content + "(자동생성글)" + auto_text
2549
2591
  end
2550
2592
 
2551
2593
  if @data['포스트설정']['내용키워드삽입'].checked?
@@ -2580,7 +2622,8 @@ class Wordpress
2580
2622
  end
2581
2623
 
2582
2624
  if @data['포스트설정']['내용을자동생성'].checked?
2583
- content2 = content.split("\n")
2625
+ #content2 = content.split("\n")
2626
+ content2 = content.split
2584
2627
  end
2585
2628
 
2586
2629
  if @data['포스트설정']['내용과자동생성'].checked? or @data['포스트설정']['gpt키워드'].checked?
@@ -3708,423 +3751,439 @@ class Wordpress
3708
3751
  }
3709
3752
  }
3710
3753
  tab_item('내용설정'){
3754
+ horizontal_box{
3755
+ vertical_box{
3711
3756
  horizontal_box{
3712
- vertical_box{
3713
- horizontal_box{
3714
- stretchy false
3715
- button('키워드불러오기'){
3716
- on_clicked{
3717
- file = open_file
3718
- if file != nil
3719
- file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3720
- file_data.split("\n").each do |keyword|
3721
- if keyword.split(' ').join('').length < 2
3722
-
3723
- else
3724
- @data['키워드설정']['키워드'] << [false, keyword]
3725
- @data['키워드설정']['키워드'] << [false, keyword]
3726
- @data['키워드설정']['키워드'].pop
3727
- end
3728
- end
3729
- end
3757
+ stretchy false
3758
+ button('키워드불러오기'){
3759
+ on_clicked{
3760
+ file = open_file
3761
+ if file != nil
3762
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3763
+ file_data.split("\n").each do |keyword|
3764
+ if keyword.split(' ').join('').length < 2
3730
3765
 
3731
- }
3732
- }
3733
-
3734
- }
3735
- horizontal_box{
3736
- stretchy false
3737
- grid{
3738
- button('전체선택'){
3739
- top 1
3740
- left 1
3741
- on_clicked{
3742
- for n in 0..@data['키워드설정']['키워드'].length-1
3743
- @data['키워드설정']['키워드'][n][0] = true
3744
- @data['키워드설정']['키워드'] << []
3745
- @data['키워드설정']['키워드'].pop
3746
- end
3747
- }
3748
- }
3749
- button('선택해제'){
3750
- top 1
3751
- left 2
3752
- on_clicked{
3753
- for n in 0..@data['키워드설정']['키워드'].length-1
3754
- @data['키워드설정']['키워드'][n][0] = false
3755
- @data['키워드설정']['키워드'] << []
3766
+ else
3767
+ @data['키워드설정']['키워드'] << [false, keyword]
3768
+ @data['키워드설정']['키워드'] << [false, keyword]
3756
3769
  @data['키워드설정']['키워드'].pop
3757
3770
  end
3758
- }
3759
- }
3760
- button('삭제하기'){
3761
- top 1
3762
- left 3
3763
- on_clicked{
3764
- m = Array.new
3765
- for n in 0..@data['키워드설정']['키워드'].length-1
3766
- if @data['키워드설정']['키워드'][n][0] == true
3767
- m << n
3768
- end
3769
- end
3771
+ end
3772
+ end
3770
3773
 
3771
- m.reverse.each do |i|
3772
- @data['키워드설정']['키워드'].delete_at(i)
3773
- end
3774
- @data['키워드설정']['키워드'].delete(nil)
3775
- }
3776
- }
3777
3774
  }
3778
-
3779
- @data['키워드설정']['순서사용'] = checkbox('순서사용'){
3780
- stretchy false
3781
- on_toggled{ |c|
3782
- if c.checked?
3783
- @data['키워드설정']['랜덤사용'].checked = false
3784
- end
3785
- }
3786
- }
3787
- @data['키워드설정']['랜덤사용'] = checkbox('랜덤사용'){
3788
- stretchy false
3789
- on_toggled{ |c|
3790
- if c.checked?
3791
- @data['키워드설정']['순서사용'].checked = false
3792
- end
3793
- }
3794
- }
3775
+ }
3776
+
3777
+ }
3778
+ horizontal_box{
3779
+ stretchy false
3780
+ grid{
3781
+ button('전체선택'){
3782
+ top 1
3783
+ left 1
3784
+ on_clicked{
3785
+ for n in 0..@data['키워드설정']['키워드'].length-1
3786
+ @data['키워드설정']['키워드'][n][0] = true
3787
+ @data['키워드설정']['키워드'] << []
3788
+ @data['키워드설정']['키워드'].pop
3789
+ end
3795
3790
  }
3796
- vertical_separator{
3797
- stretchy false
3791
+ }
3792
+ button('선택해제'){
3793
+ top 1
3794
+ left 2
3795
+ on_clicked{
3796
+ for n in 0..@data['키워드설정']['키워드'].length-1
3797
+ @data['키워드설정']['키워드'][n][0] = false
3798
+ @data['키워드설정']['키워드'] << []
3799
+ @data['키워드설정']['키워드'].pop
3800
+ end
3798
3801
  }
3799
- horizontal_box{
3800
- stretchy false
3801
- grid{
3802
- @data['포스트설정']['gpt키워드'] = checkbox('GPT 키워드 기반 글 생성'){
3803
- top 1
3804
- left 0
3805
- #enabled false # 기본적으로 비활성화
3806
- on_toggled {
3807
- if @data['포스트설정']['gpt키워드'].checked?
3808
- @data['포스트설정']['gpt상단'].enabled = true # '내용투명' 활성화
3809
- @data['포스트설정']['gpt하단'].enabled = true # '내용투명' 활성화
3810
- else
3811
- @data['포스트설정']['gpt상단'].checked = false # 체크 해제
3812
- @data['포스트설정']['gpt상단'].enabled = false # 비활성화
3813
- @data['포스트설정']['gpt하단'].checked = false # 체크 해제
3814
- @data['포스트설정']['gpt하단'].enabled = false # 비활성화
3815
- end
3816
- }
3817
-
3818
- }
3819
-
3820
- @data['포스트설정']['gpt상단'] = checkbox('원고 위에 넣기'){
3821
- top 1
3822
- left 1
3823
- enabled false # 기본적으로 비활성화
3824
- on_toggled{
3825
- if @data['포스트설정']['gpt상단'].checked?
3826
- @data['포스트설정']['gpt하단'].checked = false
3827
- end
3828
- }
3829
- }
3830
-
3831
- @data['포스트설정']['gpt하단'] = checkbox('원고 아래 넣기'){
3832
- top 1
3833
- left 2
3834
- enabled false # 기본적으로 비활성화
3835
- on_toggled{
3836
- if @data['포스트설정']['gpt하단'].checked?
3837
- @data['포스트설정']['gpt상단'].checked = false
3802
+ }
3803
+ button('삭제하기'){
3804
+ top 1
3805
+ left 3
3806
+ on_clicked{
3807
+ m = Array.new
3808
+ for n in 0..@data['키워드설정']['키워드'].length-1
3809
+ if @data['키워드설정']['키워드'][n][0] == true
3810
+ m << n
3838
3811
  end
3839
- }
3840
- }
3841
- } }
3842
- horizontal_box{
3843
- stretchy false
3844
- grid{
3845
- label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3846
- } } }
3847
-
3848
-
3849
- table{
3850
- checkbox_column('선택'){
3851
- editable true
3852
- }
3853
- text_column('키워드'){
3854
-
3855
- }
3812
+ end
3856
3813
 
3857
- cell_rows @data['키워드설정']['키워드']
3814
+ m.reverse.each do |i|
3815
+ @data['키워드설정']['키워드'].delete_at(i)
3816
+ end
3817
+ @data['키워드설정']['키워드'].delete(nil)
3858
3818
  }
3859
-
3860
-
3861
-
3862
3819
  }
3863
- vertical_separator{
3820
+ }
3821
+
3822
+ @data['키워드설정']['순서사용'] = checkbox('순서사용'){
3864
3823
  stretchy false
3824
+ on_toggled{ |c|
3825
+ if c.checked?
3826
+ @data['키워드설정']['랜덤사용'].checked = false
3827
+ end
3828
+ }
3829
+ }
3830
+ @data['키워드설정']['랜덤사용'] = checkbox('랜덤사용'){
3831
+ stretchy false
3832
+ on_toggled{ |c|
3833
+ if c.checked?
3834
+ @data['키워드설정']['순서사용'].checked = false
3835
+ end
3836
+ }
3837
+ }
3838
+ }
3839
+ vertical_separator{
3840
+ stretchy false
3841
+ }
3842
+ horizontal_box{
3843
+ stretchy false
3844
+ grid{
3845
+ @data['포스트설정']['gpt키워드'] = checkbox('GPT 키워드 기반 글 생성'){
3846
+ top 1
3847
+ left 0
3848
+ #enabled false # 기본적으로 비활성화
3849
+ on_toggled {
3850
+ if @data['포스트설정']['gpt키워드'].checked?
3851
+ @data['포스트설정']['gpt상단'].enabled = true # '내용투명' 활성화
3852
+ @data['포스트설정']['gpt하단'].enabled = true # '내용투명' 활성화
3853
+ else
3854
+ @data['포스트설정']['gpt상단'].checked = false # 체크 해제
3855
+ @data['포스트설정']['gpt상단'].enabled = false # 비활성화
3856
+ @data['포스트설정']['gpt하단'].checked = false # 체크 해제
3857
+ @data['포스트설정']['gpt하단'].enabled = false # 비활성화
3858
+ end
3859
+ }
3860
+
3861
+ }
3862
+
3863
+ @data['포스트설정']['gpt상단'] = checkbox('원고 위에 넣기'){
3864
+ top 1
3865
+ left 1
3866
+ enabled false # 기본적으로 비활성화
3867
+ on_toggled{
3868
+ if @data['포스트설정']['gpt상단'].checked?
3869
+ @data['포스트설정']['gpt하단'].checked = false
3870
+ end
3871
+ }
3865
3872
  }
3866
- vertical_box{
3867
- horizontal_box{
3868
- stretchy false
3869
- button('제목불러오기'){
3870
- on_clicked{
3871
- file = open_file
3872
- if file != nil
3873
- file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3874
- file_data.split("\n").each do |title|
3875
- if title.split(" ").join('').length < 2
3876
-
3877
- else
3878
- @data['제목설정']['제목'] << [false, title]
3879
- @data['제목설정']['제목'] << [false, title]
3880
- @data['제목설정']['제목'].pop
3881
- end
3882
- end
3883
- end
3884
- }
3885
- }
3886
3873
 
3874
+ @data['포스트설정']['gpt하단'] = checkbox('원고 아래 넣기'){
3875
+ top 1
3876
+ left 2
3877
+ enabled false # 기본적으로 비활성화
3878
+ on_toggled{
3879
+ if @data['포스트설정']['gpt하단'].checked?
3880
+ @data['포스트설정']['gpt상단'].checked = false
3881
+ end
3887
3882
  }
3888
- horizontal_box{
3889
- stretchy false
3890
- grid{
3891
- button('전체선택'){
3892
- top 1
3893
- left 1
3894
- on_clicked{
3895
- for n in 0..@data['제목설정']['제목'].length-1
3896
- @data['제목설정']['제목'][n][0] = true
3897
- @data['제목설정']['제목'] << []
3898
- @data['제목설정']['제목'].pop
3899
- end
3900
- }
3901
- }
3902
- button('선택해제'){
3903
- top 1
3904
- left 2
3905
- on_clicked{
3906
- for n in 0..@data['제목설정']['제목'].length-1
3907
- @data['제목설정']['제목'][n][0] = false
3908
- @data['제목설정']['제목'] << []
3883
+ }
3884
+ } }
3885
+ horizontal_box{
3886
+ stretchy false
3887
+ @data['포스트설정']['gpt키워드_프롬프트'] = entry(){
3888
+ text '프롬프트:관련 글을 1500자에서 2500자 사이로 만들어줘'
3889
+ }}
3890
+ horizontal_box{
3891
+ stretchy false
3892
+ grid{
3893
+ label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3894
+ } } }
3895
+
3896
+
3897
+ table{
3898
+ checkbox_column('선택'){
3899
+ editable true
3900
+ }
3901
+ text_column('키워드'){
3902
+
3903
+ }
3904
+
3905
+ cell_rows @data['키워드설정']['키워드']
3906
+ }
3907
+
3908
+
3909
+
3910
+ }
3911
+ vertical_separator{
3912
+ stretchy false
3913
+ }
3914
+ vertical_box{
3915
+ horizontal_box{
3916
+ stretchy false
3917
+ button('제목불러오기'){
3918
+ on_clicked{
3919
+ file = open_file
3920
+ if file != nil
3921
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3922
+ file_data.split("\n").each do |title|
3923
+ if title.split(" ").join('').length < 2
3924
+
3925
+ else
3926
+ @data['제목설정']['제목'] << [false, title]
3927
+ @data['제목설정']['제목'] << [false, title]
3909
3928
  @data['제목설정']['제목'].pop
3910
3929
  end
3911
- }
3912
- }
3913
- button('삭제하기'){
3914
- top 1
3915
- left 3
3916
- on_clicked{
3917
- m = Array.new
3918
- for n in 0..@data['제목설정']['제목'].length-1
3919
- if @data['제목설정']['제목'][n][0] == true
3920
- m << n
3921
- end
3922
- end
3930
+ end
3931
+ end
3932
+ }
3933
+ }
3923
3934
 
3924
- m.reverse.each do |i|
3925
- @data['제목설정']['제목'].delete_at(i)
3926
- end
3927
- @data['제목설정']['제목'].delete(nil)
3928
- }
3929
- }
3935
+ }
3936
+ horizontal_box{
3937
+ stretchy false
3938
+ grid{
3939
+ button('전체선택'){
3940
+ top 1
3941
+ left 1
3942
+ on_clicked{
3943
+ for n in 0..@data['제목설정']['제목'].length-1
3944
+ @data['제목설정']['제목'][n][0] = true
3945
+ @data['제목설정']['제목'] << []
3946
+ @data['제목설정']['제목'].pop
3947
+ end
3930
3948
  }
3931
- @data['제목설정']['순서사용'] = checkbox('순서사용'){
3932
- stretchy false
3933
- on_toggled{ |c|
3934
- if c.checked?
3935
- @data['제목설정']['랜덤사용'].checked = false
3936
- end
3937
- }
3938
- }
3939
- @data['제목설정']['랜덤사용'] = checkbox('랜덤사용'){
3940
- stretchy false
3941
- on_toggled{ |c|
3942
- if c.checked?
3943
- @data['제목설정']['순서사용'].checked = false
3944
- end
3945
- }
3946
- }
3949
+ }
3950
+ button('선택해제'){
3951
+ top 1
3952
+ left 2
3953
+ on_clicked{
3954
+ for n in 0..@data['제목설정']['제목'].length-1
3955
+ @data['제목설정']['제목'][n][0] = false
3956
+ @data['제목설정']['제목'] << []
3957
+ @data['제목설정']['제목'].pop
3958
+ end
3947
3959
  }
3948
- vertical_separator{
3949
- stretchy false
3960
+ }
3961
+ button('삭제하기'){
3962
+ top 1
3963
+ left 3
3964
+ on_clicked{
3965
+ m = Array.new
3966
+ for n in 0..@data['제목설정']['제목'].length-1
3967
+ if @data['제목설정']['제목'][n][0] == true
3968
+ m << n
3969
+ end
3970
+ end
3971
+
3972
+ m.reverse.each do |i|
3973
+ @data['제목설정']['제목'].delete_at(i)
3974
+ end
3975
+ @data['제목설정']['제목'].delete(nil)
3950
3976
  }
3951
- horizontal_box{
3952
- stretchy false
3953
- grid{
3954
- @data['포스트설정']['gpt제목'] = checkbox('제목을 이용해 GPT로 비슷한 제목 생성'){
3955
-
3956
-
3957
- }}}
3958
- horizontal_box{
3959
- stretchy false
3960
- grid{
3961
- label(' GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
3962
- } } }
3963
-
3977
+ }
3978
+ }
3979
+ @data['제목설정']['순서사용'] = checkbox('순서사용'){
3980
+ stretchy false
3981
+ on_toggled{ |c|
3982
+ if c.checked?
3983
+ @data['제목설정']['랜덤사용'].checked = false
3984
+ end
3985
+ }
3986
+ }
3987
+ @data['제목설정']['랜덤사용'] = checkbox('랜덤사용'){
3988
+ stretchy false
3989
+ on_toggled{ |c|
3990
+ if c.checked?
3991
+ @data['제목설정']['순서사용'].checked = false
3992
+ end
3993
+ }
3994
+ }
3995
+ }
3996
+ vertical_separator{
3997
+ stretchy false
3998
+ }
3999
+ horizontal_box{
4000
+ stretchy false
4001
+ grid{
4002
+ @data['포스트설정']['gpt제목'] = checkbox('제목을 이용해 GPT로 비슷한 제목 생성'){
4003
+
4004
+
4005
+ }}}
4006
+ horizontal_box{
4007
+ stretchy false
4008
+ @data['포스트설정']['gpt제목_프롬프트'] = entry(){
4009
+ text '프롬프트:비슷한 길이로 제목으로 사용할수있게 하나만 만들어줘'
4010
+ }}
4011
+ horizontal_box{
4012
+ stretchy false
4013
+ grid{
4014
+ label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
4015
+ } } }
4016
+
3964
4017
 
3965
- table{
3966
- checkbox_column('선택'){
3967
- editable true
3968
- }
3969
- text_column('제목'){
4018
+ table{
4019
+ checkbox_column('선택'){
4020
+ editable true
4021
+ }
4022
+ text_column('제목'){
3970
4023
 
3971
- }
4024
+ }
3972
4025
 
3973
- cell_rows @data['제목설정']['제목']
3974
- }
3975
-
4026
+ cell_rows @data['제목설정']['제목']
4027
+ }
4028
+
3976
4029
 
4030
+ }
4031
+ vertical_separator{
4032
+ stretchy false
4033
+ }
4034
+ vertical_box{
4035
+ horizontal_box{
4036
+ stretchy false
4037
+ button('내용불러오기'){
4038
+ on_clicked{
4039
+ file = open_file
4040
+ if file != nil
4041
+ file_name = file.split("\\")[-1]
4042
+ file_data = File.open(file,'r', :encoding => 'utf-8').read()
4043
+ if file_data.split("\n").length < 2
4044
+ file_data = file_data + "\n"
4045
+ end
4046
+ @data['내용설정']['내용'] << [false, file_name, file_data]
4047
+ @data['내용설정']['내용'] << [false, file_name, file_data]
4048
+ @data['내용설정']['내용'].pop
4049
+ end
4050
+ }
3977
4051
  }
3978
- vertical_separator{
3979
- stretchy false
3980
- }
3981
- vertical_box{
3982
- horizontal_box{
3983
- stretchy false
3984
- button('내용불러오기'){
3985
- on_clicked{
3986
- file = open_file
3987
- if file != nil
3988
- file_name = file.split("\\")[-1]
3989
- file_data = File.open(file,'r', :encoding => 'utf-8').read()
3990
- if file_data.split("\n").length < 2
3991
- file_data = file_data + "\n"
3992
- end
3993
- @data['내용설정']['내용'] << [false, file_name, file_data]
3994
- @data['내용설정']['내용'] << [false, file_name, file_data]
3995
- @data['내용설정']['내용'].pop
3996
- end
3997
- }
3998
- }
3999
4052
 
4053
+ }
4054
+ horizontal_box{
4055
+ stretchy false
4056
+ grid{
4057
+ button('전체선택'){
4058
+ top 1
4059
+ left 1
4060
+ on_clicked{
4061
+ for n in 0..@data['내용설정']['내용'].length-1
4062
+ @data['내용설정']['내용'][n][0] = true
4063
+ @data['내용설정']['내용'] << []
4064
+ @data['내용설정']['내용'].pop
4065
+ end
4000
4066
  }
4001
- horizontal_box{
4002
- stretchy false
4003
- grid{
4004
- button('전체선택'){
4005
- top 1
4006
- left 1
4007
- on_clicked{
4008
- for n in 0..@data['내용설정']['내용'].length-1
4009
- @data['내용설정']['내용'][n][0] = true
4010
- @data['내용설정']['내용'] << []
4011
- @data['내용설정']['내용'].pop
4012
- end
4013
- }
4014
- }
4015
- button('선택해제'){
4016
- top 1
4017
- left 2
4018
- on_clicked{
4019
- for n in 0..@data['내용설정']['내용'].length-1
4020
- @data['내용설정']['내용'][n][0] = false
4021
- @data['내용설정']['내용'] << []
4022
- @data['내용설정']['내용'].pop
4023
- end
4024
- }
4025
- }
4026
- button('삭제하기'){
4027
- top 1
4028
- left 3
4029
- on_clicked{
4030
- m = Array.new
4031
- for n in 0..@data['내용설정']['내용'].length-1
4032
- if @data['내용설정']['내용'][n][0] == true
4033
- m << n
4034
- end
4035
- end
4067
+ }
4068
+ button('선택해제'){
4069
+ top 1
4070
+ left 2
4071
+ on_clicked{
4072
+ for n in 0..@data['내용설정']['내용'].length-1
4073
+ @data['내용설정']['내용'][n][0] = false
4074
+ @data['내용설정']['내용'] << []
4075
+ @data['내용설정']['내용'].pop
4076
+ end
4077
+ }
4078
+ }
4079
+ button('삭제하기'){
4080
+ top 1
4081
+ left 3
4082
+ on_clicked{
4083
+ m = Array.new
4084
+ for n in 0..@data['내용설정']['내용'].length-1
4085
+ if @data['내용설정']['내용'][n][0] == true
4086
+ m << n
4087
+ end
4088
+ end
4036
4089
 
4037
- m.reverse.each do |i|
4038
- @data['내용설정']['내용'].delete_at(i)
4039
- end
4040
- @data['내용설정']['내용'].delete(nil)
4041
- }
4042
- }
4090
+ m.reverse.each do |i|
4091
+ @data['내용설정']['내용'].delete_at(i)
4092
+ end
4093
+ @data['내용설정']['내용'].delete(nil)
4043
4094
  }
4044
- @data['내용설정']['순서사용'] = checkbox('순서사용'){
4045
- stretchy false
4046
- on_toggled{ |c|
4047
- if c.checked?
4048
- @data['내용설정']['랜덤사용'].checked = false
4049
- end
4050
- }
4051
- }
4052
- @data['내용설정']['랜덤사용'] = checkbox('랜덤사용'){
4053
- stretchy false
4054
- on_toggled{ |c|
4055
- if c.checked?
4056
- @data['내용설정']['순서사용'].checked = false
4057
- end
4058
- }
4059
- }
4095
+ }
4096
+ }
4097
+ @data['내용설정']['순서사용'] = checkbox('순서사용'){
4098
+ stretchy false
4099
+ on_toggled{ |c|
4100
+ if c.checked?
4101
+ @data['내용설정']['랜덤사용'].checked = false
4102
+ end
4060
4103
  }
4061
- vertical_separator{
4062
- stretchy false
4104
+ }
4105
+ @data['내용설정']['랜덤사용'] = checkbox('랜덤사용'){
4106
+ stretchy false
4107
+ on_toggled{ |c|
4108
+ if c.checked?
4109
+ @data['내용설정']['순서사용'].checked = false
4110
+ end
4063
4111
  }
4064
- horizontal_box{
4065
- stretchy false
4066
- grid{
4067
- @data['포스트설정']['gpt내용'] = checkbox('내용파일을 이용해 GPT로 글 변형'){
4068
-
4069
-
4070
- }}}
4071
- horizontal_box{
4072
- stretchy false
4073
- grid{
4074
- label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
4075
- } } }
4076
-
4077
- table{
4078
- checkbox_column('선택'){
4079
- editable true
4080
- }
4081
- text_column('내용파일'){
4112
+ }
4113
+ }
4114
+ vertical_separator{
4115
+ stretchy false
4116
+ }
4117
+ horizontal_box{
4118
+ stretchy false
4119
+ grid{
4120
+ @data['포스트설정']['gpt내용'] = checkbox('내용파일을 이용해 GPT로 글 변형'){
4121
+
4122
+
4123
+ }}}
4124
+ horizontal_box{
4125
+ stretchy false
4126
+ @data['포스트설정']['gpt내용_프롬프트'] = entry(){
4127
+ text '프롬프트:동의어,유사어를 이용해 변경해줘'
4128
+ }}
4129
+ horizontal_box{
4130
+ stretchy false
4131
+ grid{
4132
+ label('※ GPT 기능 사용시 포스트설정1에서 GPT사용에 체크 필수'){
4133
+ } } }
4134
+
4135
+ table{
4136
+ checkbox_column('선택'){
4137
+ editable true
4138
+ }
4139
+ text_column('내용파일'){
4082
4140
 
4083
- }
4141
+ }
4084
4142
 
4085
- cell_rows @data['내용설정']['내용']
4086
- }
4143
+ cell_rows @data['내용설정']['내용']
4144
+ }
4087
4145
 
4088
- horizontal_box{
4089
- stretchy false
4090
- @data['이미지설정']['폴더경로2'] = entry{
4091
- stretchy false
4092
- text "내용폴더경로 ex)C:\\내용\\폴더1"
4093
- }
4094
- button('폴더째로 불러오기') {
4095
- on_clicked {
4096
- path = @data['이미지설정']['폴더경로2'].text.to_s.force_encoding('utf-8')
4097
-
4098
- # 경로가 유효한지 확인
4099
- if Dir.exist?(path)
4100
- Dir.entries(path).each do |file|
4101
- if file == '.' or file == '..'
4102
- next
4103
- else
4104
- begin
4105
- # 파일을 열고 내용을 읽어서 추가
4106
- file_data = File.open(path + '/' + file, 'r', encoding: 'utf-8').read
4107
- @data['내용설정']['내용'] << [false, file, file_data]
4108
- rescue => e
4109
- # 파일을 열 수 없는 경우, 오류 메시지 출력
4110
- puts "파일을 열 수 없습니다: #{file}, 오류: #{e.message}"
4111
- end
4112
- end
4113
- end
4146
+ horizontal_box{
4147
+ stretchy false
4148
+ @data['이미지설정']['폴더경로2'] = entry{
4149
+ stretchy false
4150
+ text "내용폴더경로 ex)C:\\내용\\폴더1"
4151
+ }
4114
4152
 
4115
- # 내용 배열에서 마지막 빈 항목 제거
4116
- @data['내용설정']['내용'] << []
4117
- @data['내용설정']['내용'].pop
4153
+ button('폴더째로 불러오기') {
4154
+ on_clicked {
4155
+ path = @data['이미지설정']['폴더경로2'].text.to_s.force_encoding('utf-8')
4156
+
4157
+ # 경로가 유효한지 확인
4158
+ if Dir.exist?(path)
4159
+ Dir.entries(path).each do |file|
4160
+ if file == '.' or file == '..'
4161
+ next
4118
4162
  else
4119
- # 경로가 유효하지 않을 경우, 오류 메시지 출력
4120
- puts "경로가 존재하지 않습니다: #{path}"
4163
+ begin
4164
+ # 파일을 열고 내용을 읽어서 추가
4165
+ file_data = File.open(path + '/' + file, 'r', encoding: 'utf-8').read
4166
+ @data['내용설정']['내용'] << [false, file, file_data]
4167
+ rescue => e
4168
+ # 파일을 열 수 없는 경우, 오류 메시지 출력
4169
+ puts "파일을 열 수 없습니다: #{file}, 오류: #{e.message}"
4170
+ end
4121
4171
  end
4122
- }
4123
- }
4172
+ end
4173
+
4174
+ # 내용 배열에서 마지막 빈 항목 제거
4175
+ @data['내용설정']['내용'] << []
4176
+ @data['내용설정']['내용'].pop
4177
+ else
4178
+ # 경로가 유효하지 않을 경우, 오류 메시지 출력
4179
+ puts "경로가 존재하지 않습니다: #{path}"
4180
+ end
4124
4181
  }
4125
4182
  }
4126
4183
  }
4127
4184
  }
4185
+ }
4186
+ }
4128
4187
  tab_item('이미지설정'){
4129
4188
  horizontal_box{
4130
4189
  vertical_box{
@@ -4600,7 +4659,7 @@ class Wordpress
4600
4659
  left 1
4601
4660
  text 'URL'
4602
4661
  }
4603
- @data['포스트설정']['내용을자동생성'] = checkbox('키워드기반 생성으로만 등록(GPT사용시 자체 생성)'){
4662
+ @data['포스트설정']['내용을자동생성'] = checkbox('키워드기반 글만 등록(GPT사용시 체크 해제)'){
4604
4663
  top 9
4605
4664
  left 0
4606
4665
  on_toggled{
@@ -4608,31 +4667,46 @@ class Wordpress
4608
4667
  @data['포스트설정']['내용과자동생성'].checked = false
4609
4668
  @data['포스트설정']['내용투명'].checked = false
4610
4669
  @data['포스트설정']['자동글 수식에 입력'].checked = false
4611
-
4670
+
4612
4671
  end
4613
4672
  }
4614
4673
  }
4615
-
4616
-
4674
+ label('※GPT사용시 내용설정 탭에서 설정'){
4675
+ top 9
4676
+ left 1
4677
+ }
4678
+
4679
+ label('※GPT 미 사용시 세팅 권장'){
4680
+ top 9
4681
+ left 3
4682
+ }
4683
+
4617
4684
 
4618
-
4619
4685
  aa1 = 2
4620
- @data['포스트설정']['내용과자동생성'] = checkbox('내용파일+키워드기반 생성 등록(GPT사용시 자체 생성)') {
4686
+ @data['포스트설정']['내용과자동생성'] = checkbox('원고+키워드기반 등록(GPT사용시 체크 해제)') {
4621
4687
  top 10 + aa1
4622
4688
  left 0
4623
4689
  on_toggled {
4624
- if @data['포스트설정']['내용과자동생성'].checked?
4690
+ if @data['포스트설정']['내용과자동생성'].checked?
4625
4691
  @data['포스트설정']['내용을자동생성'].checked = false
4626
4692
  @data['포스트설정']['내용투명'].enabled = true # '내용투명' 활성화
4627
4693
  @data['포스트설정']['자동글 수식에 입력'].enabled = true # '내용투명' 활성화
4628
- else
4694
+ else
4629
4695
  @data['포스트설정']['내용투명'].checked = false # 체크 해제
4630
4696
  @data['포스트설정']['내용투명'].enabled = false # 비활성화
4631
4697
  @data['포스트설정']['자동글 수식에 입력'].checked = false # 체크 해제
4632
4698
  @data['포스트설정']['자동글 수식에 입력'].enabled = false # 비활성화
4633
- end
4699
+ end
4634
4700
  }
4635
- }
4701
+ }
4702
+ label('※GPT사용시 내용설정 탭에서 설정'){
4703
+ top 10 + aa1
4704
+ left 1
4705
+ }
4706
+ label('※GPT 미 사용시 세팅 권장'){
4707
+ top 10 + aa1
4708
+ left 3
4709
+ }
4636
4710
 
4637
4711
  @data['포스트설정']['내용투명'] = checkbox('키워드 기반 자동 생성글 안보이게 처리') {
4638
4712
  top 11 + aa1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cafe_basics_duo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.55
4
+ version: 0.0.57
5
5
  platform: ruby
6
6
  authors:
7
7
  - zon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-12 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