syobocal 0.10.0 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b32b7dbb64cf8d4b48bd87da408f5607b845ab85073c025327bc6e9d6294df6
4
- data.tar.gz: 4f2ed089906d9f1560d5b0aeeaa0f009d284337069cc2794521e235ee082899c
3
+ metadata.gz: 7edc7c39022835637c4c5683b9e9192f98f5f8722b3f77218b6203227a055e17
4
+ data.tar.gz: 78e539ace20bd227556bcea06508733f8f6e30e07377bbd058e6084308a69485
5
5
  SHA512:
6
- metadata.gz: a29a2ba9cfb401f13fc69862cb283f9081fe55edb26e26618649393d0de42c97ce3759a9be5345d8bb852c59d1af453b5d4f66485dbc788851cdc7e9419cce2c
7
- data.tar.gz: 8f71e8e5941a9a40837648e9300d7cd110b1512f00bc0169185206e12e709c0a1e7c1943e8710a55684c361da01a981459511180cb217db5f425043664dc6d5b
6
+ metadata.gz: 343c5fd86a55a8d630e70660555b18e463a3fe3401b10f210dd5e1f44b619a32c4fe7f1cff2de2e7b5ada88a9bf03f7603f970ec69bc7e32d7e981409e0142a4
7
+ data.tar.gz: f0c1727b6e11244f4af5d3b9ef14eba96deb4244e7aef2322277f21a70d23414d5ce36b333a2ed853761822d3d1c6b1e0c09923afea85f66e0976d8be50a3e6a
data/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  ## 概要
4
4
 
5
- syobocalは[しょぼいカレンダー](http://cal.syoboi.jp/)からデータを取得するためのRubyスクリプトです。
6
- sch_uploadを除いて仕様が公開されている以下20種類のエンドポイントすべてに対応しています。
5
+ syobocalは[しょぼいカレンダー](http://cal.syoboi.jp/)からデータを取得するためのRubyスクリプトです。`sch_upload`を除いて仕様が公開されている以下20種類のエンドポイントすべてに対応しています。
7
6
 
8
7
  - cal_chk.php
9
8
  - db.php
@@ -49,12 +48,110 @@ sch_uploadを除いて仕様が公開されている以下20種類のエンド
49
48
  XMLやRSSをパースした結果は値が適切な型に変換されたハッシュの配列です。
50
49
  JSONをパースした結果はJSONのデータ構造をそのまま返します。
51
50
 
52
- ~~~~
51
+ いくつか典型的だろう使い方を紹介します。
52
+
53
+ 以下は`db.php`からアニメごとに採番された`TID`とタイトルを一覧で取得する例です。
54
+
55
+ ```ruby
53
56
  require 'syobocal'
54
57
  require 'pp'
55
- params = {"TID" => "1"}
56
- pp Syobocal::DB::TitleLookup.get(params)
57
- ~~~~
58
+
59
+ pp Syobocal::DB::TitleLookup.get({'TID' => '*', 'Fields' => 'TID,Title'})
60
+ # [{:tid=>1, :title=>"魔法遣いに大切なこと"},
61
+ # {:tid=>2, :title=>"ソニックX"},
62
+ # {:tid=>3, :title=>"デ・ジ・キャラットにょ"},
63
+ # {:tid=>1224, :title=>"魔法先生ネギま!(実写版)"},
64
+ # {:tid=>3601, :title=>"新妹魔王の契約者"},
65
+ # {:tid=>3588, :title=>"アイドルマスター シンデレラガールズ"},
66
+ # {:tid=>4, :title=>"妄想科学シリーズ ワンダバスタイル"},
67
+ # {:tid=>1086, :title=>"ひとひら"},
68
+ # {:tid=>5, :title=>"DEARBOYS"},
69
+ # {:tid=>6, :title=>"LAST EXILE"},
70
+ # ...
71
+ ```
72
+
73
+ 以下は`TID`指定で特定のアニメのデータを取得する例です。
74
+
75
+ ```ruby
76
+ require 'syobocal'
77
+ require 'pp'
78
+
79
+ title = Syobocal::DB::TitleLookup.get({'TID' => '2077'})
80
+ pp title.first
81
+ # {:tid=>2077,
82
+ # :last_update=>2013-12-02 02:17:55 +0900,
83
+ # :title=>"魔法少女まどか☆マギカ",
84
+ # :short_title=>"まどか☆マギカ",
85
+ # :title_yomi=>"まほうしょうじょまどかまぎか",
86
+ # :title_en=>"PUELLA MAGI MADOKA MAGICA",
87
+ # :comment=>
88
+ # "*リンク\n" +
89
+ # "-[[公式 http://www.madoka-magica.com/tv/]]\n" +
90
+ # "-[[MBS http://www.mbs.jp/madoka-magica/]]\n" +
91
+ # "-[[ニコニコチャンネル http://ch.nicovideo.jp/ch260]]\n" +
92
+ # "-[[TOKYO MX http://www.mxtv.co.jp/madoka_magica/]]\n" +
93
+ # "-[[BS11デジタル http://www.bs11.jp/anime/2360/]]\n" +
94
+ # "*メモ\n" +
95
+ # "-アニマックスでのリピート放送は放送日の27:00~と日曜26:00~\n" +
96
+ # "*スタッフ\n" +
97
+ # ":原作:Magica Quartet\n" +
98
+ # ":監督:新房昭之\n" +
99
+ # ":キャラクター原案:蒼樹うめ\n" +
100
+ # ":キャラクターデザイン:岸田隆宏\n" +
101
+ # ...
102
+ ```
103
+
104
+ APIリクエスト時のパラメータは`syobocal`ライブラリとして解釈しません。しょぼいカレンダーのAPI仕様を参照して下さい。また`'TID' => '*'`に代表される大量のデータ取得はしばしば10MB以上の巨大なレスポンスを返します。しょぼいカレンダー側も大変だろうと思うので、使い方は考えて下さい。
105
+
106
+ ### コメントパーサ(ベータ版)
107
+
108
+ しょぼいカレンダーの`comment`属性にはスタッフやキャストなど多岐に渡る情報が専用の記法で格納されています。バージョン`0.11`以降の`syobocal`ライブラリはコメントパーサ(`Syobocal::Comment::Parser`)を備え、それらの情報を意味的に扱いやすい形で取り出すことができます。コメントパーサはベータ版です。インタフェースは変更される可能性があります。
109
+
110
+ ```ruby
111
+ require 'syobocal'
112
+ require 'pp'
113
+
114
+ title = Syobocal::DB::TitleLookup.get({'TID' => '2077'})
115
+ comment = title.first[:comment]
116
+ parser = Syobocal::Comment::Parser.new(comment)
117
+
118
+ pp parser.links.first
119
+ # #<Syobocal::Comment::Element::Link:0x0000564600b42e30
120
+ # @str="公式",
121
+ # @url="http://www.madoka-magica.com/tv/">
122
+
123
+ pp parser.staffs.first
124
+ # #<Syobocal::Comment::Staff:0x00005645ffc60048
125
+ # @people=
126
+ # [#<Syobocal::Comment::Person:0x00005645ffc60368
127
+ # @name="Magica Quartet",
128
+ # @note=nil>],
129
+ # @role="原作">
130
+
131
+ pp parser.casts.first
132
+ # #<Syobocal::Comment::Cast:0x0000564600051b70
133
+ # @character="鹿目まどか",
134
+ # @people=
135
+ # [#<Syobocal::Comment::Person:0x0000564600051cd8 @name="悠木碧", @note=nil>]>
136
+
137
+ pp parser.musics.first
138
+ # #<Syobocal::Comment::Music:0x00005646000afc98
139
+ # @category="オープニングテーマ",
140
+ # @data_list=
141
+ # [#<Syobocal::Comment::MusicData:0x00005646000a0b30
142
+ # @attr="作詞・作曲",
143
+ # @value="渡辺翔">,
144
+ # #<Syobocal::Comment::MusicData:0x00005646000a06a8
145
+ # @attr="主題歌協力",
146
+ # @value="外村敬一">,
147
+ # #<Syobocal::Comment::MusicData:0x00005646000a0428
148
+ # @attr="歌",
149
+ # @value="ClariS">,
150
+ # #<Syobocal::Comment::MusicData:0x00005646000afd38
151
+ # @attr="使用話数",
152
+ # @value="#1~#9、#11">],
153
+ # @title="コネクト">
154
+ ```
58
155
 
59
156
  ## おまけ
60
157
 
@@ -109,7 +206,7 @@ $ syobocal-anime
109
206
 
110
207
  ## 作者
111
208
 
112
- - [xmisao](http://www.xmisao.com/)
209
+ - [xmisao](https://www.xmisao.com/)
113
210
 
114
211
  ## ライセンス
115
212
 
data/Rakefile CHANGED
@@ -1,2 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
- task :default => :spec
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ task :default => :test
File without changes
@@ -1,15 +1,31 @@
1
- require 'open-uri'
2
- require 'rexml/document'
3
- require 'delegate'
4
- require 'json'
5
- require 'rss'
1
+ require "open-uri"
2
+ require "rexml/document"
3
+ require "delegate"
4
+ require "json"
5
+ require "rss"
6
6
  require "syobocal/version"
7
7
 
8
- require 'syobocal/util.rb'
9
- require 'syobocal/calchk.rb'
10
- require 'syobocal/db.rb'
11
- require 'syobocal/json.rb'
12
- require 'syobocal/rss.rb'
13
- require 'syobocal/rss2.rb'
8
+ require "syobocal/util"
9
+ require "syobocal/calchk"
10
+ require "syobocal/db"
11
+ require "syobocal/json"
12
+ require "syobocal/rss"
13
+ require "syobocal/rss2"
14
+ require "syobocal/comment/element/blank"
15
+ require "syobocal/comment/element/header1"
16
+ require "syobocal/comment/element/header2"
17
+ require "syobocal/comment/element/link"
18
+ require "syobocal/comment/element/list"
19
+ require "syobocal/comment/element/row"
20
+ require "syobocal/comment/element/text"
21
+ require "syobocal/comment/element/text_node"
22
+ require "syobocal/comment/element/root"
23
+ require "syobocal/comment/parser"
24
+ require "syobocal/comment/staff"
25
+ require "syobocal/comment/cast"
26
+ require "syobocal/comment/person"
27
+ require "syobocal/comment/music"
28
+ require "syobocal/comment/music_data"
29
+ require "syobocal/comment/section"
14
30
 
15
31
  module Syobocal; end
@@ -5,7 +5,7 @@ module Syobocal
5
5
  end
6
6
 
7
7
  def url(params = {})
8
- 'http://cal.syoboi.jp/cal_chk.php' + Syobocal::Util.format_params(params)
8
+ "http://cal.syoboi.jp/cal_chk.php" + Syobocal::Util.format_params(params)
9
9
  end
10
10
 
11
11
  def parse(xml)
@@ -13,14 +13,14 @@ module Syobocal
13
13
 
14
14
  result = Result.new
15
15
 
16
- syobocal = xml.elements['syobocal']
16
+ syobocal = xml.elements["syobocal"]
17
17
  result.url = syobocal.attribute("url").to_s
18
18
  result.version = syobocal.attribute("version").to_s
19
19
  result.last_update = Time.parse(syobocal.attribute("LastUpdate").to_s)
20
20
  result.spid = syobocal.attribute("SPID").to_s
21
21
  result.spname = syobocal.attribute("SPNAME").to_s
22
22
 
23
- xml.elements.each('syobocal/ProgItems/ProgItem'){|item|
23
+ xml.elements.each("syobocal/ProgItems/ProgItem") { |item|
24
24
  result << {
25
25
  :pid => item.attribute("PID").to_s.to_i,
26
26
  :tid => item.attribute("TID").to_s.to_i,
@@ -32,7 +32,7 @@ module Syobocal
32
32
  :st_offset => item.attribute("StOffset").to_s.to_i,
33
33
  :sub_title => item.attribute("SubTitle").to_s,
34
34
  :title => item.attribute("Title").to_s,
35
- :prog_comment => item.attribute("ProgComment").to_s
35
+ :prog_comment => item.attribute("ProgComment").to_s,
36
36
  }
37
37
  }
38
38
 
@@ -0,0 +1,15 @@
1
+ module Syobocal
2
+ module Comment
3
+ class Cast
4
+ attr_reader :character, :people
5
+
6
+ def initialize(character, people)
7
+ @character, @people = character, people
8
+ end
9
+
10
+ def ==(other)
11
+ other.instance_of?(self.class) && other.character == character && other.people == people
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ module Syobocal
2
+ module Comment
3
+ module Element
4
+ class Blank
5
+ def initialize; end
6
+
7
+ def ==(other)
8
+ other.instance_of?(self.class)
9
+ end
10
+
11
+ def inner_text
12
+ ""
13
+ end
14
+
15
+ def self.match?(line)
16
+ line.match(/\A\s*\Z/)
17
+ end
18
+
19
+ def self.parse(line)
20
+ Element::Blank.new
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ module Syobocal
2
+ module Comment
3
+ module Element
4
+ class Header1
5
+ attr_reader :text_node
6
+
7
+ def initialize(text_node)
8
+ @text_node = text_node
9
+ end
10
+
11
+ def ==(other)
12
+ other.instance_of?(self.class) && other.text_node == text_node
13
+ end
14
+
15
+ def self.match?(line)
16
+ !Header2.match?(line) && line.start_with?("*")
17
+ end
18
+
19
+ def self.parse(line)
20
+ txt = line.match(/\A\*(.*)\Z/)[1]
21
+
22
+ Element::Header1.new(Element::TextNode.parse(txt))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module Syobocal
2
+ module Comment
3
+ module Element
4
+ class Header2
5
+ attr_reader :text_node
6
+
7
+ def initialize(text_node)
8
+ @text_node = text_node
9
+ end
10
+
11
+ def ==(other)
12
+ other.instance_of?(self.class) && other.text_node == text_node
13
+ end
14
+
15
+ def self.match?(line)
16
+ line.start_with?("**")
17
+ end
18
+
19
+ def self.parse(line)
20
+ txt = line.match(/\A\*\*(.*)\Z/)[1]
21
+
22
+ Element::Header2.new(Element::TextNode.parse(txt))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ module Syobocal
2
+ module Comment
3
+ module Element
4
+ class Link
5
+ attr_reader :str, :url
6
+
7
+ def initialize(str, url)
8
+ @str, @url = str, url
9
+ end
10
+
11
+ def ==(other)
12
+ other.instance_of?(self.class) && other.str == str && other.url == url
13
+ end
14
+
15
+ def self.create(text)
16
+ inner_str = text.match(/\A\[\[(.*)\]\]\Z/)[1]
17
+
18
+ sep = inner_str.split(/ /)
19
+
20
+ if ["http://", "https://", "archive://"].any? { |scheme| sep.last.start_with?(scheme) }
21
+ link = sep.pop
22
+ new(sep.join(" "), link)
23
+ else
24
+ new(sep.join(" "), nil)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ module Syobocal
2
+ module Comment
3
+ module Element
4
+ class List
5
+ attr_reader :text_node
6
+
7
+ def initialize(text_node)
8
+ @text_node = text_node
9
+ end
10
+
11
+ def ==(other)
12
+ other.instance_of?(self.class) && other.text_node == text_node
13
+ end
14
+
15
+ def self.match?(line)
16
+ line.start_with?("-")
17
+ end
18
+
19
+ def self.parse(line)
20
+ txt = line.match(/\A-(.*)\Z/)[1]
21
+
22
+ Element::List.new(Element::TextNode.parse(txt))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ module Syobocal
2
+ module Comment
3
+ module Element
4
+ class Root
5
+ attr_reader :elements
6
+
7
+ def initialize(elements)
8
+ @elements = elements
9
+ end
10
+
11
+ def ==(other)
12
+ other.elements == elements
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ module Syobocal
2
+ module Comment
3
+ module Element
4
+ class Row
5
+ attr_reader :attr_node, :value_node
6
+
7
+ def initialize(attr_node, value_node)
8
+ @attr_node, @value_node = attr_node, value_node
9
+ end
10
+
11
+ def ==(other)
12
+ other.instance_of?(self.class) && other.attr_node == attr_node && other.value_node == value_node
13
+ end
14
+
15
+ def self.match?(line)
16
+ line.start_with?(":")
17
+ end
18
+
19
+ def self.parse(line)
20
+ if line.scan(":").length == 1
21
+ # NOTE :が1つしか含まれない行は:以降が値となる
22
+ m = line.match(/\A:(.*)\Z/)
23
+ attr = Element::Blank.new
24
+ value = Element::TextNode.parse(m[1])
25
+ else
26
+ m = line.match(/\A:([^:]*?):(.*)\Z/)
27
+ attr = Element::TextNode.parse(m[1])
28
+ value = Element::TextNode.parse(m[2])
29
+ end
30
+
31
+ Element::Row.new(attr, value)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end