tdiary-contrib 5.2.4 → 5.4.0
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/tdiary/contrib/version.rb +1 -1
- data/plugin/chatgpt_elaborate.rb +135 -0
- data/plugin/image_ex.rb +7 -13
- data/plugin/microsummary.rb +1 -1
- data/plugin/yahoo_kousei.rb +30 -17
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ea6ac9aa57f48f37e87e0487488694fedde1f3b36f9a352532975e205a9a0b8
|
4
|
+
data.tar.gz: 9e33bee8f1c7fa448357428e5ba06f5574553d3b37fb0a7b031cfaa00c557632
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e3ac23fa672b189da7a9e19cc3b6b24d46c66e30b2d32fd58dd74dff13009863d54340501fafe6c231ceab537c3570ccd11f893d3b6a4b79b69df52ab9a425d
|
7
|
+
data.tar.gz: 9e8db2d64a4c054da3ba8dfcd947b435fcfe3e4a86b66dd5be9e5c33a902e66486fe01201adde278b4b8dbff3348bcdc2430b3108b75e04ed2822a8101ee357b
|
@@ -0,0 +1,135 @@
|
|
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
|
+
# @options['chatgpt_elaborate.MAX_TOKEN'] : 応答最大トークン数(default:2000 トークン)
|
30
|
+
# @options['chatgpt_elaborate.READ_TIMEOUT'] : 応答最大待ち時間(default:90 秒)
|
31
|
+
# @options['chatgpt_elaborate.TEMPERATURE'] : 温度(default: 0.7)
|
32
|
+
|
33
|
+
require 'timeout'
|
34
|
+
require 'json'
|
35
|
+
require 'net/http'
|
36
|
+
require 'net/https'
|
37
|
+
require 'cgi'
|
38
|
+
#Net::HTTP.version_1_2
|
39
|
+
|
40
|
+
def elaborate_api( sentence )
|
41
|
+
#@logger.debug( "ChatGPT elaborate")
|
42
|
+
apiKey = @conf['chatgpt_elaborate.OPENAI_API_KEY']
|
43
|
+
model = @conf['chatgpt_elaborate.OPENAI_API_MODEL']||'gpt-3.5-turbo'
|
44
|
+
azureKey = @conf['chatgpt_elaborate.AZURE_OPENAI_API_KEY']
|
45
|
+
instanceName = @conf['chatgpt_elaborate.AZURE_OPENAI_API_INSTANCE_NAME']
|
46
|
+
deploymentName = @conf['chatgpt_elaborate.AZURE_OPENAI_API_DEPLOYMENT_NAME']
|
47
|
+
version = @conf['chatgpt_elaborate.AZURE_OPENAI_API_VERSION']||'2023-05-15'
|
48
|
+
maxToken = @conf['chatgpt_elaborate.MAX_TOKEN']||2000
|
49
|
+
readTimeout = @conf['chatgpt_elaborate.READ_TIMEOUT']||90
|
50
|
+
temperature = @conf['chatgpt_elaborate.TEMPERATURE']||0.7
|
51
|
+
|
52
|
+
messages = [
|
53
|
+
{"role" => "system",
|
54
|
+
"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 MUST not remove the spaces before the HTML tag at the beginning of the line. 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." },
|
55
|
+
{ "role" => "user",
|
56
|
+
"content" => "#{sentence}" }]
|
57
|
+
|
58
|
+
if ( azureKey )
|
59
|
+
#@logger.debug( "ChatGPT elaborate by Azure OpenAI API")
|
60
|
+
url = URI.parse("https://"\
|
61
|
+
+ instanceName + ".openai.azure.com"\
|
62
|
+
+ "/openai/deployments/" + deploymentName\
|
63
|
+
+ "/chat/completions"\
|
64
|
+
+ "?api-version=" + version )
|
65
|
+
params = {
|
66
|
+
'messages' => messages,
|
67
|
+
"temperature" => temperature,
|
68
|
+
"max_tokens" => maxToken,
|
69
|
+
#"top_p" => 0.1,
|
70
|
+
"frequency_penalty" => 0,
|
71
|
+
"presence_penalty" => 0 }
|
72
|
+
headers = {'Content-Type' => 'application/json',
|
73
|
+
'api-key' => azureKey }
|
74
|
+
else
|
75
|
+
#@logger.debug( "ChatGPT elaborate by Original OpenAI API")
|
76
|
+
url = URI.parse("https://api.openai.com/v1/chat/completions")
|
77
|
+
params = {
|
78
|
+
"model" => model,
|
79
|
+
'messages' => messages,
|
80
|
+
"temperature" => temperature,
|
81
|
+
"max_tokens" => maxToken,
|
82
|
+
#"top_p" => 0.1,
|
83
|
+
"frequency_penalty" => 0,
|
84
|
+
"presence_penalty" => 0 }
|
85
|
+
headers = {'Content-Type' => 'application/json',
|
86
|
+
'Authorization' => "Bearer #{apiKey}" }
|
87
|
+
end
|
88
|
+
px_host, px_port = (@conf['proxy'] || '').split( /:/ )
|
89
|
+
px_port = 80 if px_host and !px_port
|
90
|
+
|
91
|
+
json = ''
|
92
|
+
Net::HTTP::Proxy( px_host, px_port ).start( url.host, url.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_PEER, read_timeout: readTimeout ) do |http|
|
93
|
+
#@logger.debug( "POST #{url} #{params.to_json}" )
|
94
|
+
json = http.post(url.request_uri, params.to_json, headers ).body
|
95
|
+
#@logger.debug( "\nRESPONSE #{json}" )
|
96
|
+
end
|
97
|
+
json
|
98
|
+
end
|
99
|
+
|
100
|
+
def elaborate_result( json )
|
101
|
+
html = <<-HTML
|
102
|
+
<h3>OpenAI 推敲結果</h3>
|
103
|
+
HTML
|
104
|
+
|
105
|
+
doc = JSON.parse( json )
|
106
|
+
if doc["error"]
|
107
|
+
html << "<p>Error: #{doc["error"]["message"]}<br/>"
|
108
|
+
html << "Type: #{doc["error"]["type"]}<br/>"
|
109
|
+
html << "Code: #{doc["error"]["code"]}</p>"
|
110
|
+
else
|
111
|
+
result = doc["choices"][0]["message"]["content"]
|
112
|
+
if result.empty?
|
113
|
+
html << "<p>見つかりませんでした。</p>"
|
114
|
+
else
|
115
|
+
html << '<p>'
|
116
|
+
html << CGI::escapeHTML(result).gsub( /\n/, '<br />' )
|
117
|
+
html << '</p>'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
html
|
121
|
+
end
|
122
|
+
|
123
|
+
add_edit_proc do
|
124
|
+
if @mode == 'preview' &&
|
125
|
+
( @conf['chatgpt_elaborate.AZURE_OPENAI_API_KEY'] ||
|
126
|
+
@conf['chatgpt_elaborate.OPENAI_API_KEY'] )then
|
127
|
+
json = elaborate_api( @cgi.params['body'][0] )
|
128
|
+
<<-HTML
|
129
|
+
<div id="plugin_chatgpt_elaborate" class="section">
|
130
|
+
#{elaborate_result( json )}
|
131
|
+
</div>
|
132
|
+
HTML
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
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,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tdiary-contrib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tDiary contributors
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tdiary
|
@@ -259,6 +259,7 @@ files:
|
|
259
259
|
- plugin/category_similar.rb
|
260
260
|
- plugin/category_to_tag.rb
|
261
261
|
- plugin/category_to_tagcloud.rb
|
262
|
+
- plugin/chatgpt_elaborate.rb
|
262
263
|
- plugin/cocomment.rb
|
263
264
|
- plugin/code-prettify.rb
|
264
265
|
- plugin/coderay.rb
|
@@ -529,7 +530,7 @@ homepage: http://www.tdiary.org/
|
|
529
530
|
licenses:
|
530
531
|
- GPL-2 and/or others
|
531
532
|
metadata: {}
|
532
|
-
post_install_message:
|
533
|
+
post_install_message:
|
533
534
|
rdoc_options: []
|
534
535
|
require_paths:
|
535
536
|
- lib
|
@@ -544,8 +545,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
544
545
|
- !ruby/object:Gem::Version
|
545
546
|
version: '0'
|
546
547
|
requirements: []
|
547
|
-
rubygems_version: 3.
|
548
|
-
signing_key:
|
548
|
+
rubygems_version: 3.5.22
|
549
|
+
signing_key:
|
549
550
|
specification_version: 4
|
550
551
|
summary: tDiary contributions package
|
551
552
|
test_files:
|