nblog_zon 0.0.75 → 0.0.79
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 +168 -87
- 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: 90f5b5abe540ae0b9c9aa6fe9ff2d0dd4995853214960b6891368585b3d7de90
|
4
|
+
data.tar.gz: b8ece68d61b394efa5dd1ba090dd1abd77c3fc46ebed845f7812a26543a5b614
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10d0b9dd93709d013ecbb02c04a392336f9ee36d7218fae8fd1c5133f29d50a69eeaae29d172e428ae0b3698ea7e0a267a089346d63658ce98e1bac841be83c6
|
7
|
+
data.tar.gz: e715db872cc696a71cc70374bbe7916bd9359e4ec2b4aac7713fc27284075792cb596318b0a49b2099bf6d28716a2173e6cf77d258785c8da81170b32fb09796
|
data/lib/nblog_zon.rb
CHANGED
@@ -22,93 +22,107 @@ using Rainbow
|
|
22
22
|
include Glimmer
|
23
23
|
|
24
24
|
class Chat
|
25
|
-
def initialize(api_key)
|
25
|
+
def initialize(api_key, gpt_keyword_prompt)
|
26
26
|
@api_key = api_key
|
27
|
+
@gpt_keyword_prompt = gpt_keyword_prompt
|
27
28
|
end
|
28
29
|
|
29
|
-
def
|
30
|
-
|
31
|
-
h = {
|
32
|
-
'Content-Type' => 'application/json',
|
33
|
-
'Authorization' => 'Bearer ' + @api_key
|
34
|
-
}
|
35
|
-
d = {
|
36
|
-
#'model' => 'gpt-3.5-turbo',
|
37
|
-
'model' => 'gpt-4',
|
38
|
-
'messages' => [{
|
39
|
-
"role" => "assistant",
|
40
|
-
"content" => keyword.to_s+" 소개하는 글을 1500자에서 2500자 사이로 만들어줘"
|
41
|
-
}]
|
42
|
-
}
|
43
|
-
answer = ''
|
44
|
-
begin
|
45
|
-
req = HTTP.headers(h).post(url, :json => d)
|
46
|
-
print(req.to_s)
|
47
|
-
answer = JSON.parse(req.to_s)['choices'][0]['message']['content']
|
48
|
-
rescue => e
|
49
|
-
begin
|
50
|
-
answer = JSON.parse(req.to_s)['choices'][0]['message']['message']
|
51
|
-
rescue
|
30
|
+
def message(keyword)
|
31
|
+
puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'
|
52
32
|
|
33
|
+
# "키워드 기반 글 생성 중..." 메시지 출력 스레드
|
34
|
+
thread = Thread.new do
|
35
|
+
while true
|
36
|
+
print "▶"
|
37
|
+
sleep 3
|
53
38
|
end
|
54
39
|
end
|
55
40
|
|
56
|
-
|
57
|
-
print('api return ==> ')
|
58
|
-
puts(answer)
|
59
|
-
|
60
|
-
return answer
|
61
|
-
end
|
62
|
-
|
63
|
-
def message(keyword)
|
64
|
-
puts 'chat gpt ...'
|
65
41
|
url = 'https://api.openai.com/v1/chat/completions'
|
66
|
-
|
42
|
+
headers = {
|
67
43
|
'Content-Type' => 'application/json',
|
68
44
|
'Authorization' => 'Bearer ' + @api_key
|
69
45
|
}
|
70
|
-
|
71
|
-
|
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 = {
|
72
55
|
'model' => 'gpt-4',
|
73
|
-
'messages' => [
|
74
|
-
|
75
|
-
|
76
|
-
|
56
|
+
'messages' => [
|
57
|
+
{
|
58
|
+
"role" => "assistant",
|
59
|
+
"content" => "#{keyword}\n#{@gpt_keyword_prompt}"
|
60
|
+
}
|
61
|
+
],
|
62
|
+
'max_tokens' => max_response_tokens # 최대 응답 토큰 설정
|
77
63
|
}
|
64
|
+
|
65
|
+
|
66
|
+
|
78
67
|
answer = ''
|
79
68
|
begin
|
80
|
-
req = HTTP.headers(
|
81
|
-
print(req.to_s)
|
82
|
-
answer = JSON.parse(req.to_s)['choices'][0]['message']['content']
|
83
|
-
rescue => e
|
84
|
-
begin
|
85
|
-
answer = JSON.parse(req.to_s)['choices'][0]['message']['message']
|
86
|
-
rescue
|
69
|
+
req = HTTP.headers(headers).post(url, :json => data)
|
87
70
|
|
71
|
+
# 상태 코드 확인
|
72
|
+
if req.status != 200
|
73
|
+
raise "HTTP Error: #{req.status}, Response Body: #{req.body.to_s}"
|
88
74
|
end
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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"
|
95
85
|
end
|
96
|
-
|
86
|
+
rescue => e
|
87
|
+
# 오류 메시지 출력
|
88
|
+
puts "Error occurred: #{e.message}"
|
89
|
+
answer = "오류가 발생했습니다."
|
97
90
|
end
|
98
91
|
|
99
|
-
|
100
|
-
|
92
|
+
# "생성 중..." 메시지 출력 종료
|
93
|
+
thread.kill
|
101
94
|
|
95
|
+
# 결과 로그 출력
|
96
|
+
puts "Final API response ==> #{answer}"
|
102
97
|
return answer
|
103
98
|
end
|
99
|
+
|
100
|
+
def calculate_tokens(text)
|
101
|
+
# 간단한 방식으로 텍스트의 토큰 수 계산 (정확도는 다를 수 있음)
|
102
|
+
# OpenAI API는 1토큰이 대략 4글자 정도임
|
103
|
+
text.split(/\s+/).length # 간단한 단어 수로 계산
|
104
|
+
end
|
104
105
|
end
|
105
106
|
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
106
111
|
class Chat_title
|
107
|
-
def initialize(api_key)
|
112
|
+
def initialize(api_key, gpt_title_prompt)
|
108
113
|
@api_key = api_key
|
114
|
+
@gpt_title_prompt = gpt_title_prompt
|
109
115
|
end
|
110
116
|
|
111
117
|
def message(title)
|
118
|
+
puts 'Sending request to GPT...(제목 생성 중...)'
|
119
|
+
# "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
|
120
|
+
thread = Thread.new do
|
121
|
+
while true
|
122
|
+
print "▶"
|
123
|
+
sleep(3)
|
124
|
+
end
|
125
|
+
end
|
112
126
|
url = 'https://api.openai.com/v1/chat/completions'
|
113
127
|
headers = {
|
114
128
|
'Content-Type' => 'application/json',
|
@@ -122,15 +136,15 @@ class Chat_title
|
|
122
136
|
},
|
123
137
|
{
|
124
138
|
"role" => "user",
|
125
|
-
"content" => "#{
|
139
|
+
"content" => "#{@gpt_title_prompt}\n#{title}"
|
126
140
|
}]
|
127
141
|
}
|
128
142
|
|
129
143
|
begin
|
130
144
|
req = HTTP.headers(headers).post(url, json: data)
|
131
|
-
|
145
|
+
|
132
146
|
response = JSON.parse(req.body.to_s)
|
133
|
-
|
147
|
+
|
134
148
|
|
135
149
|
if req.status == 429
|
136
150
|
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
@@ -138,11 +152,18 @@ class Chat_title
|
|
138
152
|
|
139
153
|
# 응답 데이터에서 안전하게 값 추출
|
140
154
|
answer = response.dig('choices', 0, 'message', 'content')
|
141
|
-
|
155
|
+
|
156
|
+
# 따옴표 제거
|
157
|
+
answer = answer.gsub('"', '') if answer
|
158
|
+
|
159
|
+
answer ||= title # 응답이 없을 경우 기본 메시지 설정
|
142
160
|
rescue => e
|
143
161
|
puts "Error: #{e.message}"
|
144
162
|
answer = "오류가 발생했습니다."
|
145
163
|
end
|
164
|
+
|
165
|
+
# "생성 중..." 메시지 출력 종료
|
166
|
+
thread.kill
|
146
167
|
|
147
168
|
puts 'API return ==> '
|
148
169
|
puts answer
|
@@ -150,12 +171,23 @@ class Chat_title
|
|
150
171
|
end
|
151
172
|
end
|
152
173
|
|
174
|
+
|
153
175
|
class Chat_content
|
154
|
-
def initialize(api_key)
|
176
|
+
def initialize(api_key, gpt_content_prompt)
|
155
177
|
@api_key = api_key
|
178
|
+
@gpt_content_prompt = gpt_content_prompt
|
156
179
|
end
|
157
180
|
|
158
181
|
def message(content)
|
182
|
+
puts 'Sending request to GPT...(내용 변형 중...)'
|
183
|
+
puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'
|
184
|
+
# "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
|
185
|
+
thread = Thread.new do
|
186
|
+
while true
|
187
|
+
print "▶"
|
188
|
+
sleep(3)
|
189
|
+
end
|
190
|
+
end
|
159
191
|
|
160
192
|
url = 'https://api.openai.com/v1/chat/completions'
|
161
193
|
headers = {
|
@@ -170,15 +202,16 @@ class Chat_content
|
|
170
202
|
},
|
171
203
|
{
|
172
204
|
"role" => "user",
|
173
|
-
"content" => "#{content}
|
205
|
+
"content" => "#{@gpt_content_prompt}\n#{content}"
|
206
|
+
|
174
207
|
}]
|
175
208
|
}
|
176
209
|
|
177
210
|
begin
|
178
211
|
req = HTTP.headers(headers).post(url, json: data)
|
179
|
-
|
212
|
+
|
180
213
|
response = JSON.parse(req.body.to_s)
|
181
|
-
|
214
|
+
|
182
215
|
|
183
216
|
if req.status == 429
|
184
217
|
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
@@ -192,6 +225,9 @@ class Chat_content
|
|
192
225
|
answer = "오류가 발생했습니다."
|
193
226
|
end
|
194
227
|
|
228
|
+
# "생성 중..." 메시지 출력 종료
|
229
|
+
thread.kill
|
230
|
+
|
195
231
|
puts 'API return ==> '
|
196
232
|
puts answer
|
197
233
|
answer
|
@@ -199,6 +235,7 @@ class Chat_content
|
|
199
235
|
end
|
200
236
|
|
201
237
|
|
238
|
+
|
202
239
|
#############################################gpt############################################
|
203
240
|
|
204
241
|
class Naver
|
@@ -2338,16 +2375,17 @@ class Wordpress
|
|
2338
2375
|
# ADB 서버 초기화
|
2339
2376
|
puts 'adb kill-server'
|
2340
2377
|
Open3.capture3('./adb kill-server')
|
2341
|
-
sleep(
|
2378
|
+
sleep(3)
|
2342
2379
|
|
2343
2380
|
# 다시 ADB 서버 실행
|
2344
2381
|
puts 'adb start-server'
|
2345
2382
|
Open3.capture3('./adb start-server')
|
2346
|
-
sleep(
|
2383
|
+
sleep(3)
|
2347
2384
|
|
2348
2385
|
# 데이터를 끄고 켜기
|
2349
2386
|
puts 'adb -s ' + device_id + ' shell svc data disable'
|
2350
2387
|
stdout2, stderr2, status2 = Open3.capture3('./adb -s '+device_id+' shell svc data disable')
|
2388
|
+
sleep(3)
|
2351
2389
|
puts 'adb -s ' + device_id + ' shell svc data enable'
|
2352
2390
|
Open3.capture3('./adb -s '+device_id+' shell svc data enable')
|
2353
2391
|
sleep(3)
|
@@ -2392,10 +2430,19 @@ class Wordpress
|
|
2392
2430
|
end
|
2393
2431
|
|
2394
2432
|
if @data['포스트설정']['gpt제목'].checked?
|
2395
|
-
|
2433
|
+
gpt_title_prompt = @data['포스트설정']['gpt제목_프롬프트'].text.to_s.force_encoding('utf-8')
|
2434
|
+
|
2435
|
+
# 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
|
2436
|
+
gpt_title_prompt_sample = gpt_title_prompt.strip.empty? ? "프롬프트: 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘." : gpt_title_prompt
|
2437
|
+
|
2438
|
+
# gpt_title_prompt_sample을 Chat_title 객체에 전달
|
2439
|
+
chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample)
|
2440
|
+
|
2441
|
+
# 메시지 요청 후 title에 저장
|
2396
2442
|
gpt_text1 = chat.message(title)
|
2397
2443
|
title = gpt_text1.to_s
|
2398
2444
|
end
|
2445
|
+
|
2399
2446
|
|
2400
2447
|
|
2401
2448
|
@data['table'][index][-1] = 5
|
@@ -2438,18 +2485,16 @@ class Wordpress
|
|
2438
2485
|
|
2439
2486
|
|
2440
2487
|
if @data['포스트설정']['gpt내용'].checked?
|
2488
|
+
gpt_content_prompt = @data['포스트설정']['gpt내용_프롬프트'].text.to_s.force_encoding('utf-8')
|
2441
2489
|
api_key = @data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8')
|
2442
|
-
#key_change = @data['포스트설정']['특정단어키워드로변경값'].text.to_s.force_encoding('utf-8')
|
2443
|
-
#imotcon_change = @data['포스트설정']['스티커로변경단어'].text.to_s.force_encoding('utf-8')
|
2444
|
-
#template_change = @data['포스트설정']['내템플릿변경단어'].text.to_s.force_encoding('utf-8')
|
2445
|
-
#ttdanar_change = @data['포스트설정']['단어링크적용단어'].text.to_s.force_encoding('utf-8')
|
2446
|
-
#sajine_change = @data['포스트설정']['단어사진으로변경단어'].text.to_s.force_encoding('utf-8')
|
2447
|
-
#mov_change = @data['포스트설정']['영상으로변경단어'].text.to_s.force_encoding('utf-8')
|
2448
|
-
#map_change = @data['포스트설정']['지도로변경단어'].text.to_s.force_encoding('utf-8')
|
2449
|
-
#inyong9_change = @data['포스트설정']['인용구변경단어'].text.to_s.force_encoding('utf-8')
|
2450
|
-
|
2451
2490
|
|
2452
|
-
|
2491
|
+
# 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
|
2492
|
+
gpt_content_prompt_sample = gpt_content_prompt.strip.empty? ? "프롬프트:ChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해" : gpt_content_prompt
|
2493
|
+
|
2494
|
+
# Chat_content 객체 생성 시 api_key와 gpt_content_prompt_sample을 두 개의 인자로 전달
|
2495
|
+
chat = Chat_content.new(api_key, gpt_content_prompt_sample)
|
2496
|
+
|
2497
|
+
# 메시지 요청 후 content에 저장
|
2453
2498
|
gpt_text3 = chat.message(content)
|
2454
2499
|
content = gpt_text3.to_s
|
2455
2500
|
end
|
@@ -2653,13 +2698,17 @@ class Wordpress
|
|
2653
2698
|
@data['table'] << []
|
2654
2699
|
@data['table'].pop
|
2655
2700
|
if @data['포스트설정']['gpt키워드'].checked?
|
2656
|
-
|
2701
|
+
gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
|
2702
|
+
gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
|
2703
|
+
chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
|
2657
2704
|
gpt_text = chat.message(keyword)
|
2658
|
-
content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
|
2705
|
+
#content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
|
2706
|
+
content = content.to_s + "(자동생성글)" + gpt_text.to_s
|
2659
2707
|
elsif @data['포스트설정']['내용을자동생성'].checked?
|
2660
2708
|
content = auto_text
|
2661
2709
|
elsif @data['포스트설정']['내용과자동생성'].checked?
|
2662
|
-
content = content + "\n(자동생성글)\n" + auto_text
|
2710
|
+
#content = content + "\n(자동생성글)\n" + auto_text
|
2711
|
+
content = content + "(자동생성글)" + auto_text
|
2663
2712
|
end
|
2664
2713
|
|
2665
2714
|
if @data['포스트설정']['내용키워드삽입'].checked?
|
@@ -2694,7 +2743,8 @@ class Wordpress
|
|
2694
2743
|
end
|
2695
2744
|
|
2696
2745
|
if @data['포스트설정']['내용을자동생성'].checked?
|
2697
|
-
content2 = content.split("\n")
|
2746
|
+
#content2 = content.split("\n")
|
2747
|
+
content2 = content.split
|
2698
2748
|
end
|
2699
2749
|
|
2700
2750
|
if @data['포스트설정']['내용과자동생성'].checked? or @data['포스트설정']['gpt키워드'].checked?
|
@@ -4009,6 +4059,11 @@ class Wordpress
|
|
4009
4059
|
}
|
4010
4060
|
}
|
4011
4061
|
} }
|
4062
|
+
horizontal_box{
|
4063
|
+
stretchy false
|
4064
|
+
@data['포스트설정']['gpt키워드_프롬프트'] = entry(){
|
4065
|
+
text '프롬프트:관련 글을 1500자에서 2500자 사이로 만들어줘'
|
4066
|
+
}}
|
4012
4067
|
horizontal_box{
|
4013
4068
|
stretchy false
|
4014
4069
|
grid{
|
@@ -4125,6 +4180,11 @@ class Wordpress
|
|
4125
4180
|
|
4126
4181
|
|
4127
4182
|
}}}
|
4183
|
+
horizontal_box{
|
4184
|
+
stretchy false
|
4185
|
+
@data['포스트설정']['gpt제목_프롬프트'] = entry(){
|
4186
|
+
text '프롬프트:비슷한 길이로 제목으로 사용할수있게 하나만 만들어줘'
|
4187
|
+
}}
|
4128
4188
|
horizontal_box{
|
4129
4189
|
stretchy false
|
4130
4190
|
grid{
|
@@ -4238,6 +4298,11 @@ class Wordpress
|
|
4238
4298
|
|
4239
4299
|
|
4240
4300
|
}}}
|
4301
|
+
horizontal_box{
|
4302
|
+
stretchy false
|
4303
|
+
@data['포스트설정']['gpt내용_프롬프트'] = entry(){
|
4304
|
+
text '프롬프트:동의어,유사어를 이용해 변경해줘'
|
4305
|
+
}}
|
4241
4306
|
horizontal_box{
|
4242
4307
|
stretchy false
|
4243
4308
|
grid{
|
@@ -4847,7 +4912,7 @@ class Wordpress
|
|
4847
4912
|
left 1
|
4848
4913
|
text 'URL'
|
4849
4914
|
}
|
4850
|
-
@data['포스트설정']['내용을자동생성'] = checkbox('키워드기반
|
4915
|
+
@data['포스트설정']['내용을자동생성'] = checkbox('키워드기반 글만 등록(GPT사용시 체크 해제)'){
|
4851
4916
|
top 9
|
4852
4917
|
left 0
|
4853
4918
|
on_toggled{
|
@@ -4859,10 +4924,19 @@ class Wordpress
|
|
4859
4924
|
end
|
4860
4925
|
}
|
4861
4926
|
}
|
4862
|
-
|
4863
|
-
|
4927
|
+
label('※GPT사용시 내용설정 탭에서 설정'){
|
4928
|
+
top 9
|
4929
|
+
left 1
|
4930
|
+
}
|
4931
|
+
|
4932
|
+
label('※GPT 미 사용시 세팅 권장'){
|
4933
|
+
top 9
|
4934
|
+
left 3
|
4935
|
+
}
|
4936
|
+
|
4937
|
+
|
4864
4938
|
aa1 = 2
|
4865
|
-
@data['포스트설정']['내용과자동생성'] = checkbox('
|
4939
|
+
@data['포스트설정']['내용과자동생성'] = checkbox('원고+키워드기반 글 등록(GPT사용시 체크 해제)') {
|
4866
4940
|
top 10 + aa1
|
4867
4941
|
left 0
|
4868
4942
|
on_toggled {
|
@@ -4878,7 +4952,14 @@ class Wordpress
|
|
4878
4952
|
end
|
4879
4953
|
}
|
4880
4954
|
}
|
4881
|
-
|
4955
|
+
label('※GPT사용시 내용설정 탭에서 설정'){
|
4956
|
+
top 10 + aa1
|
4957
|
+
left 1
|
4958
|
+
}
|
4959
|
+
label('※GPT 미 사용시 세팅 권장'){
|
4960
|
+
top 10 + aa1
|
4961
|
+
left 3
|
4962
|
+
}
|
4882
4963
|
@data['포스트설정']['내용투명'] = checkbox('키워드 기반 자동 생성글 안보이게 처리') {
|
4883
4964
|
top 11 + aa1
|
4884
4965
|
left 0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nblog_zon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.79
|
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-
|
11
|
+
date: 2025-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: File to Clipboard gem
|
14
14
|
email: rnjstnswp123@naver.com
|