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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd4d72bbf85abaac2b85a812fc08cdc3cc9141481aa68b30c7058da77e6ffcc1
4
- data.tar.gz: 2fa4f105853169aaa3cd28cbb91af940d45a41400ece3e56d9e3059f729fdc50
3
+ metadata.gz: d28e4c6ad18e641ce3998648c7b1735ad42f439ffe868c5cef97f28ac8e9d018
4
+ data.tar.gz: cc978600003b50b6bfed72750e6e4ba0cb90ffa8433d89be583d9a8289e3fa86
5
5
  SHA512:
6
- metadata.gz: 83b45d584917dd4fa197c4f68b323330251e7f029e019cfeebd7519a895f06c6b1951b0b59ff2fb1855b3edb38301246ed012ee7d00c666665135ab080283210
7
- data.tar.gz: d87353d94f0da9f295844748693639f660254581da8fd727068ab84985d41905e5b98937d7e3102671ea72c816cbbbd4704b32b94e5602c5fd951799a8fa040e
6
+ metadata.gz: d489a23467625b99e58f3bbd090bef40ff0ae16f3caaa6913f5a9c2314d8554e01954546c547ca35bab2ccb2d6e7597baac675fa9e0fb79e81f0178a614a0788
7
+ data.tar.gz: 23879c32c58ed959ae16e09e12727e5376b0b60bb368b071def02888308453e09d03f383a4d8fccb3e678e30af3d96a42bc1918d931d1b22dc9acd8e475aec38
@@ -1,5 +1,5 @@
1
1
  module TDiary
2
2
  class Contrib
3
- VERSION = "5.2.4"
3
+ VERSION = "5.3.0"
4
4
  end
5
5
  end
@@ -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).untaint
113
- slist = imageList(@image_date, image_dir, "s").untaint
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).untaint
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.untaint
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.untaint
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.untaint
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'].untaint.each do |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
@@ -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::exists? @conf['generator.xml']
55
+ create_xml( @conf['generator.xml'] ) unless File::exist? @conf['generator.xml']
56
56
  end
57
57
 
58
58
  if @mode == 'saveconf'
@@ -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
- # 設定値は http://developer.yahoo.co.jp/webapi/jlp/kousei/v1/kousei.html を参照
15
+ # 設定値は https://developer.yahoo.co.jp/webapi/jlp/kousei/v2/kousei.html を参照
19
16
  #
20
17
 
21
18
  require 'timeout'
22
- require 'rexml/document'
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
- query = "appid=#{appid}&sentence=#{CGI.escape( sentence.gsub( /\n/, '' ) )}"
30
- query << "&filter_group=" + @conf['yahoo_kousei.filter_group'] if @conf['yahoo_kousei.filter_group']
31
- query << "&no_filter=" + @conf['yahoo_kousei.no_filter'] if @conf['yahoo_kousei.no_filter']
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/V1/kousei', query ).body
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 = REXML::Document::new( result_set )
49
- results = REXML::XPath.match( doc, "//Result" )
50
- if results.empty?
51
- html << "<p>指摘項目は見つかりませんでした。</p>"
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
- doc.elements.each( '//ResultSet/Result' ) do |r|
56
- html << %Q|<tr class="plugin_yahoo_search_result_raw"><td>#{r.elements['Surface'].text}</td><td>#{r.elements['ShitekiWord'].text}</td><td>#{r.elements['ShitekiInfo'].text}</td><td>#{r.elements['StartPos'].text},#{r.elements['Length'].text}</td></tr>|
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.2.4
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: 2022-11-29 00:00:00.000000000 Z
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.3.26
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: