tdiary-contrib 5.2.4 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/tdiary/contrib/version.rb +1 -1
- data/plugin/chatgpt_elaborate.rb +128 -0
- data/plugin/image_ex.rb +7 -13
- data/plugin/microsummary.rb +1 -1
- data/plugin/yahoo_kousei.rb +30 -17
- metadata +4 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d28e4c6ad18e641ce3998648c7b1735ad42f439ffe868c5cef97f28ac8e9d018
|
4
|
+
data.tar.gz: cc978600003b50b6bfed72750e6e4ba0cb90ffa8433d89be583d9a8289e3fa86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d489a23467625b99e58f3bbd090bef40ff0ae16f3caaa6913f5a9c2314d8554e01954546c547ca35bab2ccb2d6e7597baac675fa9e0fb79e81f0178a614a0788
|
7
|
+
data.tar.gz: 23879c32c58ed959ae16e09e12727e5376b0b60bb368b071def02888308453e09d03f383a4d8fccb3e678e30af3d96a42bc1918d931d1b22dc9acd8e475aec38
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# chatgtp_elaborate.rb -
|
4
|
+
# tDiary用のプラグインです。OpenAI APIでChatGPTを利用して、
|
5
|
+
# 日本語文の遂行作業を支援します。文字の入力ミスや言葉の誤用がないか、
|
6
|
+
# わかりにくい表記や不適切な表現が使われていないかなどをチェックします。
|
7
|
+
# 本家OpenAI APIとArure OpenAI ServiceのOpenAI APIでテストています。
|
8
|
+
# https://azure.microsoft.com/products/cognitive-services/openai-service
|
9
|
+
#
|
10
|
+
# Copyright (c) 2010, hb <http://www.smallstyle.com/>
|
11
|
+
# Copyright (c) 2023, Takuya Ono <takuya-o@users.osdn.me>
|
12
|
+
# You can redistribute it and/or modify it under GPL.
|
13
|
+
#
|
14
|
+
# 設定:
|
15
|
+
#
|
16
|
+
# 本家OpenAIか、Azure OpenAIかによってどちらかが必須
|
17
|
+
# @options['chatgpt_elaborate.OPENAI_API_KEY'] : API_KEY(どちらか必須)
|
18
|
+
# @options['chatgpt_elaborate.AZURE_OPENAI_API_KEY'] : API_KEY(どちらか必須)
|
19
|
+
#
|
20
|
+
# 本家OpenAIのオプション
|
21
|
+
# @options['chatgpt_elaborate.OPENAI_API_MODEL'] : モデル名 "gpt-3.5-turbo"
|
22
|
+
#
|
23
|
+
# 以下はAzure OpenAI APIを利用する時に必須
|
24
|
+
# @options['chatgpt_elaborate.AZURE_OPENAI_API_INSTANCE_NAME'] : インスタンス名
|
25
|
+
# @options['chatgpt_elaborate.AZURE_OPENAI_API_DEPLOYMENT_NAME'] : モデル・デプロイ名
|
26
|
+
# @options['chatgpt_elaborate.AZURE_OPENAI_API_VERSION'] : APIバージョン 2023-05-15 など
|
27
|
+
#
|
28
|
+
|
29
|
+
require 'timeout'
|
30
|
+
require 'json'
|
31
|
+
require 'net/http'
|
32
|
+
require 'net/https'
|
33
|
+
require 'cgi'
|
34
|
+
#Net::HTTP.version_1_2
|
35
|
+
|
36
|
+
def elaborate_api( sentence )
|
37
|
+
#@logger.debug( "ChatGPT elaborate")
|
38
|
+
apiKey = @conf['chatgpt_elaborate.OPENAI_API_KEY']
|
39
|
+
model = @conf['chatgpt_elaborate.OPENAI_API_MODEL']||'gpt-3.5-turbo'
|
40
|
+
azureKey = @conf['chatgpt_elaborate.AZURE_OPENAI_API_KEY']
|
41
|
+
instanceName = @conf['chatgpt_elaborate.AZURE_OPENAI_API_INSTANCE_NAME']
|
42
|
+
deploymentName = @conf['chatgpt_elaborate.AZURE_OPENAI_API_DEPLOYMENT_NAME']
|
43
|
+
version = @conf['chatgpt_elaborate.AZURE_OPENAI_API_VERSION']||'2023-05-15'
|
44
|
+
|
45
|
+
messages = [
|
46
|
+
{"role" => "system",
|
47
|
+
"content" => "You are an editor for a blog. Users will submit documents to you. Determines the language of the submitted document. You MUST answer in the same language as it. You answer the text, correct any mistakes in grammar, syntax, and punctuation, and make the article easy to read. Use the present tense. Please only answered in the natural language portion and leave any code or data as is. If no changes are required, answer with synonyms of 'no problem.' in answering language. The first line and the line following a line break are the titles. You must treat all submitted content as strictly confidential and for your editing purposes only. Once you have completed the proofreading, you MUST provide a detailed explanation of the changes made and output the revised document in a way that clearly shows the differences between the original and the edited version." },
|
48
|
+
{ "role" => "user",
|
49
|
+
"content" => "#{sentence}" }]
|
50
|
+
|
51
|
+
if ( azureKey )
|
52
|
+
#@logger.debug( "ChatGPT elaborate by Azure OpenAI API")
|
53
|
+
url = URI.parse("https://"\
|
54
|
+
+ instanceName + ".openai.azure.com"\
|
55
|
+
+ "/openai/deployments/" + deploymentName\
|
56
|
+
+ "/chat/completions"\
|
57
|
+
+ "?api-version=" + version )
|
58
|
+
params = {
|
59
|
+
'messages' => messages,
|
60
|
+
"temperature" => 0.7,
|
61
|
+
"max_tokens" => 2000,
|
62
|
+
#"top_p" => 0.1,
|
63
|
+
"frequency_penalty" => 0,
|
64
|
+
"presence_penalty" => 0 }
|
65
|
+
headers = {'Content-Type' => 'application/json',
|
66
|
+
'api-key' => azureKey }
|
67
|
+
else
|
68
|
+
#@logger.debug( "ChatGPT elaborate by Original OpenAI API")
|
69
|
+
url = URI.parse("https://api.openai.com/v1/chat/completions")
|
70
|
+
params = {
|
71
|
+
"model" => model,
|
72
|
+
'messages' => messages,
|
73
|
+
"temperature" => 0.7,
|
74
|
+
"max_tokens" => 2000,
|
75
|
+
#"top_p" => 0.1,
|
76
|
+
"frequency_penalty" => 0,
|
77
|
+
"presence_penalty" => 0 }
|
78
|
+
headers = {'Content-Type' => 'application/json',
|
79
|
+
'Authorization' => "Bearer #{apiKey}" }
|
80
|
+
end
|
81
|
+
px_host, px_port = (@conf['proxy'] || '').split( /:/ )
|
82
|
+
px_port = 80 if px_host and !px_port
|
83
|
+
|
84
|
+
json = ''
|
85
|
+
Net::HTTP::Proxy( px_host, px_port ).start( url.host, url.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_PEER ) do |http|
|
86
|
+
#@logger.debug( "POST #{url} #{params.to_json}" )
|
87
|
+
json = http.post(url.request_uri, params.to_json, headers ).body
|
88
|
+
#@logger.debug( "\nRESPONSE #{json}" )
|
89
|
+
end
|
90
|
+
json
|
91
|
+
end
|
92
|
+
|
93
|
+
def elaborate_result( json )
|
94
|
+
html = <<-HTML
|
95
|
+
<h3>OpenAI 推敲結果</h3>
|
96
|
+
HTML
|
97
|
+
|
98
|
+
doc = JSON.parse( json )
|
99
|
+
if doc["error"]
|
100
|
+
html << "<p>Error: #{doc["error"]["message"]}<br/>"
|
101
|
+
html << "Type: #{doc["error"]["type"]}<br/>"
|
102
|
+
html << "Code: #{doc["error"]["code"]}</p>"
|
103
|
+
else
|
104
|
+
result = doc["choices"][0]["message"]["content"]
|
105
|
+
if result.empty?
|
106
|
+
html << "<p>見つかりませんでした。</p>"
|
107
|
+
else
|
108
|
+
html << '<p>'
|
109
|
+
html << CGI::escapeHTML(result).gsub( /\n/, '<br />' )
|
110
|
+
html << '</p>'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
html
|
114
|
+
end
|
115
|
+
|
116
|
+
add_edit_proc do
|
117
|
+
if @mode == 'preview' &&
|
118
|
+
( @conf['chatgpt_elaborate.AZURE_OPENAI_API_KEY'] ||
|
119
|
+
@conf['chatgpt_elaborate.OPENAI_API_KEY'] )then
|
120
|
+
json = elaborate_api( @cgi.params['body'][0] )
|
121
|
+
<<-HTML
|
122
|
+
<div id="plugin_chatgpt_elaborate" class="section">
|
123
|
+
#{elaborate_result( json )}
|
124
|
+
</div>
|
125
|
+
HTML
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
data/plugin/image_ex.rb
CHANGED
@@ -106,11 +106,10 @@ def image( id, alt = "image", id2 = nil, width = nil, place="none" )
|
|
106
106
|
image_dir = %Q[#{@image_dir}/]
|
107
107
|
end
|
108
108
|
|
109
|
-
image_dir.untaint
|
110
109
|
Dir.mkdir(image_dir) unless File.directory?(image_dir)
|
111
110
|
|
112
|
-
list = imageList(@image_date, image_dir)
|
113
|
-
slist = imageList(@image_date, image_dir, "s")
|
111
|
+
list = imageList(@image_date, image_dir)
|
112
|
+
slist = imageList(@image_date, image_dir, "s")
|
114
113
|
|
115
114
|
if width
|
116
115
|
width_tag = %Q[width="#{h width}"]
|
@@ -150,7 +149,7 @@ def image_link( id, str )
|
|
150
149
|
image_url = %Q[#{@image_url}/]
|
151
150
|
image_dir = %Q[#{@image_dir}/]
|
152
151
|
end
|
153
|
-
list = imageList(@image_date, image_dir)
|
152
|
+
list = imageList(@image_date, image_dir)
|
154
153
|
%Q[<a href="#{h image_url}#{h list[id.to_i]}">#{str}</a>]
|
155
154
|
end
|
156
155
|
|
@@ -240,7 +239,6 @@ add_form_proc do |date|
|
|
240
239
|
|
241
240
|
def dayimagelist( image_dir, image_date, prefix="")
|
242
241
|
image_path = []
|
243
|
-
image_dir.untaint
|
244
242
|
Dir.foreach(image_dir){ |file|
|
245
243
|
if file=~ /(.*)\_(.*)\.(.*)/
|
246
244
|
if $1 == "#{prefix}" + image_date.to_s
|
@@ -252,7 +250,7 @@ add_form_proc do |date|
|
|
252
250
|
end
|
253
251
|
|
254
252
|
if @cgi.params['plugin_image_add'][0] && @cgi.params['plugin_image_file'][0].original_filename != ''
|
255
|
-
image_dir = @cgi.params['plugin_image_dir'][0].read
|
253
|
+
image_dir = @cgi.params['plugin_image_dir'][0].read
|
256
254
|
image_filename = ''
|
257
255
|
image_extension = ''
|
258
256
|
image_date = date.strftime("%Y%m%d")
|
@@ -263,7 +261,6 @@ add_form_proc do |date|
|
|
263
261
|
image_name = dayimagelist(image_dir, image_date)
|
264
262
|
image_file = image_dir+image_date+"_"+image_name.length.to_s+image_extension.downcase
|
265
263
|
|
266
|
-
image_file.untaint
|
267
264
|
File::umask( 022 )
|
268
265
|
File::open( image_file, "wb" ) {|f|
|
269
266
|
f.print @cgi.params['plugin_image_file'][0].read
|
@@ -300,17 +297,16 @@ add_form_proc do |date|
|
|
300
297
|
end
|
301
298
|
|
302
299
|
elsif @cgi.params['plugin_image_thumbnail'][0] && @cgi.params['plugin_image_file'][0].original_filename != ''
|
303
|
-
image_dir = @cgi.params['plugin_image_dir'][0].read
|
300
|
+
image_dir = @cgi.params['plugin_image_dir'][0].read
|
304
301
|
image_filename = ''
|
305
302
|
image_extension = ''
|
306
303
|
image_date = date.strftime("%Y%m%d")
|
307
304
|
image_filename = @cgi.params['plugin_image_file'][0].original_filename
|
308
305
|
if image_filename =~ /(\.jpg|\.jpeg|\.gif|\.png)\z/i
|
309
306
|
image_extension = $1
|
310
|
-
image_name = @cgi.params['plugin_image_name'][0].read
|
307
|
+
image_name = @cgi.params['plugin_image_name'][0].read
|
311
308
|
image_file=image_dir+"s"+image_name+image_extension.downcase
|
312
309
|
|
313
|
-
image_file.untaint
|
314
310
|
File::umask( 022 )
|
315
311
|
File::open( image_file, "wb" ) {|f|
|
316
312
|
f.print @cgi.params['plugin_image_file'][0].read
|
@@ -323,17 +319,15 @@ add_form_proc do |date|
|
|
323
319
|
image_name = dayimagelist( image_dir, image_date)
|
324
320
|
image_name2= dayimagelist( image_dir, image_date, "s")
|
325
321
|
|
326
|
-
@cgi.params['plugin_image_id'].
|
322
|
+
@cgi.params['plugin_image_id'].each do |id|
|
327
323
|
if image_name[id.to_i]
|
328
324
|
image_file=image_dir+image_name[id.to_i]
|
329
|
-
image_file.untaint
|
330
325
|
if File::exist?(image_file)
|
331
326
|
File::delete(image_file)
|
332
327
|
end
|
333
328
|
end
|
334
329
|
if image_name2[id.to_i]
|
335
330
|
image_file2=image_dir+image_name2[id.to_i]
|
336
|
-
image_file2.untaint
|
337
331
|
if File::exist?(image_file2)
|
338
332
|
File::delete(image_file2)
|
339
333
|
end
|
data/plugin/microsummary.rb
CHANGED
@@ -52,7 +52,7 @@ end
|
|
52
52
|
|
53
53
|
def microsummary_init
|
54
54
|
@conf['generator.xml'] ||= ""
|
55
|
-
create_xml( @conf['generator.xml'] ) unless File::
|
55
|
+
create_xml( @conf['generator.xml'] ) unless File::exist? @conf['generator.xml']
|
56
56
|
end
|
57
57
|
|
58
58
|
if @mode == 'saveconf'
|
data/plugin/yahoo_kousei.rb
CHANGED
@@ -5,37 +5,41 @@
|
|
5
5
|
# わかりにくい表記や不適切な表現が使われていないかなどをチェックします。
|
6
6
|
#
|
7
7
|
# Copyright (c) 2010, hb <http://www.smallstyle.com/>
|
8
|
+
# Copyright (c) 2023, Takuya Ono <takuya-o@users.osdn.me>
|
8
9
|
# You can redistribute it and/or modify it under GPL.
|
9
10
|
#
|
10
11
|
# 設定:
|
11
12
|
#
|
12
13
|
# @options['yahoo_kousei.appid'] : アプリケーションID(必須)
|
13
|
-
# @options['yahoo_kousei.filter_group'] :
|
14
|
-
# 指摘グループの番号をコンマで区切って指定します。
|
15
|
-
# @options['yahoo_kousei.no_filter'] :
|
16
|
-
# filter_groupで指定した指摘グループから除外する指摘を指定します。
|
17
14
|
#
|
18
|
-
# 設定値は
|
15
|
+
# 設定値は https://developer.yahoo.co.jp/webapi/jlp/kousei/v2/kousei.html を参照
|
19
16
|
#
|
20
17
|
|
21
18
|
require 'timeout'
|
22
|
-
require '
|
19
|
+
require 'json'
|
23
20
|
require 'net/http'
|
21
|
+
require 'net/https'
|
24
22
|
Net::HTTP.version_1_2
|
25
23
|
|
26
24
|
def kousei_api( sentence )
|
27
25
|
appid = @conf['yahoo_kousei.appid']
|
26
|
+
headers = {'Content-Type' => 'application/json',
|
27
|
+
'User-Agent' => "Yahoo AppID: #{appid}" }
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
query = { "id" => 1234,
|
30
|
+
"jsonrpc" => "2.0",
|
31
|
+
"method" => "jlp.kouseiservice.kousei",
|
32
|
+
"params" => {
|
33
|
+
"q" => sentence
|
34
|
+
}
|
35
|
+
}
|
32
36
|
|
33
37
|
px_host, px_port = (@conf['proxy'] || '').split( /:/ )
|
34
38
|
px_port = 80 if px_host and !px_port
|
35
39
|
|
36
40
|
xml = ''
|
37
|
-
Net::HTTP::Proxy( px_host, px_port ).start( 'jlp.yahooapis.jp' ) do |http|
|
38
|
-
xml = http.post( '/KouseiService/
|
41
|
+
Net::HTTP::Proxy( px_host, px_port ).start( 'jlp.yahooapis.jp', 443, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_PEER ) do |http|
|
42
|
+
xml = http.post( '/KouseiService/V2/kousei', query.to_json, headers ).body
|
39
43
|
end
|
40
44
|
xml
|
41
45
|
end
|
@@ -45,15 +49,24 @@ def kousei_result( result_set )
|
|
45
49
|
<h3>文章校正結果</h3>
|
46
50
|
HTML
|
47
51
|
|
48
|
-
doc =
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
+
doc = JSON.parse( result_set )
|
53
|
+
errormsg = ""
|
54
|
+
if doc["Error"] != nil
|
55
|
+
errormsg = doc["Error"]["Message"]
|
56
|
+
doc = { "result" => { "suggestions" => [] } }
|
57
|
+
end
|
58
|
+
results = doc['result']['suggestions']
|
59
|
+
if results.length == 0
|
60
|
+
if errormsg == ""
|
61
|
+
html << "<p>指摘項目は見つかりませんでした。</p>"
|
62
|
+
else
|
63
|
+
html << "<p>Error: #{errormsg}</p>"
|
64
|
+
end
|
52
65
|
else
|
53
66
|
html << '<table>'
|
54
67
|
html << '<tr><th>対象表記</th><th>候補文字</th><th>詳細情報</th><th>場所</th></tr>'
|
55
|
-
|
56
|
-
html << %Q|<tr class="plugin_yahoo_search_result_raw"><td>#{r
|
68
|
+
results.each do |r|
|
69
|
+
html << %Q|<tr class="plugin_yahoo_search_result_raw"><td>#{r['word']}</td><td>#{r['suggestion']}</td><td>#{r['rule']} #{r['note']}</td><td>#{r['offset']},#{r['length']}</td></tr>|
|
57
70
|
end
|
58
71
|
html << '</table>'
|
59
72
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tdiary-contrib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tDiary contributors
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2024-02-29 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: tdiary
|
@@ -259,6 +258,7 @@ files:
|
|
259
258
|
- plugin/category_similar.rb
|
260
259
|
- plugin/category_to_tag.rb
|
261
260
|
- plugin/category_to_tagcloud.rb
|
261
|
+
- plugin/chatgpt_elaborate.rb
|
262
262
|
- plugin/cocomment.rb
|
263
263
|
- plugin/code-prettify.rb
|
264
264
|
- plugin/coderay.rb
|
@@ -529,7 +529,6 @@ homepage: http://www.tdiary.org/
|
|
529
529
|
licenses:
|
530
530
|
- GPL-2 and/or others
|
531
531
|
metadata: {}
|
532
|
-
post_install_message:
|
533
532
|
rdoc_options: []
|
534
533
|
require_paths:
|
535
534
|
- lib
|
@@ -544,8 +543,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
544
543
|
- !ruby/object:Gem::Version
|
545
544
|
version: '0'
|
546
545
|
requirements: []
|
547
|
-
rubygems_version: 3.
|
548
|
-
signing_key:
|
546
|
+
rubygems_version: 3.6.0.dev
|
549
547
|
specification_version: 4
|
550
548
|
summary: tDiary contributions package
|
551
549
|
test_files:
|