aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile1
-rw-r--r--core/lib/diva_hacks/entity.rb8
-rw-r--r--core/lib/diva_hacks/entity/basic_twitter_entity.rb (renamed from core/lib/retriever/entity/basic_twitter_entity.rb)0
-rw-r--r--core/lib/diva_hacks/entity/blank_entity.rb (renamed from core/lib/retriever/entity/blank_entity.rb)0
-rw-r--r--core/lib/diva_hacks/entity/extended_twitter_entity.rb (renamed from core/lib/retriever/entity/extended_twitter_entity.rb)0
-rw-r--r--core/lib/diva_hacks/entity/regexp_entity.rb (renamed from core/lib/retriever/entity/regexp_entity.rb)0
-rw-r--r--core/lib/diva_hacks/entity/segment.rb (renamed from core/lib/retriever/entity/segment.rb)0
-rw-r--r--core/lib/diva_hacks/entity/url_entity.rb (renamed from core/lib/retriever/entity/url_entity.rb)0
-rw-r--r--core/lib/diva_hacks/mixin.rb6
-rw-r--r--core/lib/diva_hacks/mixin/message_mixin.rb (renamed from core/lib/retriever/mixin/message_mixin.rb)0
-rw-r--r--core/lib/diva_hacks/mixin/photo_mixin.rb (renamed from core/lib/retriever/mixin/photo_mixin.rb)0
-rw-r--r--core/lib/diva_hacks/mixin/user_mixin.rb (renamed from core/lib/retriever/mixin/user_mixin.rb)0
-rw-r--r--core/lib/diva_hacks/model.rb147
-rw-r--r--core/lib/diva_hacks/model/identity.rb (renamed from core/lib/retriever/model/identity.rb)0
-rw-r--r--core/lib/diva_hacks/model/memory.rb (renamed from core/lib/retriever/model/memory.rb)0
-rw-r--r--core/lib/retriever.rb47
-rw-r--r--core/lib/retriever/cast.rb26
-rw-r--r--core/lib/retriever/datasource.rb33
-rw-r--r--core/lib/retriever/error.rb19
-rw-r--r--core/lib/retriever/field_generator.rb39
-rw-r--r--core/lib/retriever/model.rb421
-rw-r--r--core/lib/retriever/spec.rb9
-rw-r--r--core/lib/retriever/uri.rb131
-rw-r--r--core/message.rb15
-rw-r--r--core/mui/gtk_photo_pixbuf.rb1
-rw-r--r--core/plugin/activity/activity.rb27
-rw-r--r--core/plugin/activity/model/activity.rb2
-rw-r--r--core/plugin/core/core.rb6
-rw-r--r--core/plugin/openimg/model/photo.rb1
-rw-r--r--core/plugin/photo/model/photo.rb1
-rw-r--r--core/plugin/skin/model/image.rb1
-rw-r--r--core/system/message.rb1
-rw-r--r--core/system/user.rb1
-rwxr-xr-xmikutter.rb1
-rw-r--r--test/core/test_retriever.rb28
35 files changed, 215 insertions, 757 deletions
diff --git a/Gemfile b/Gemfile
index f78c1820..e047676b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -11,6 +11,7 @@ group :default do
gem 'oauth', '>= 0.5.1'
gem 'json_pure', '~> 1.8'
gem 'addressable', '~> 2.3'
+ gem 'diva'
gem 'memoist', '~> 0.14'
gem 'ruby-hmac', '~> 0.4'
gem 'typed-array', '~> 0.1'
diff --git a/core/lib/diva_hacks/entity.rb b/core/lib/diva_hacks/entity.rb
new file mode 100644
index 00000000..90ac62c2
--- /dev/null
+++ b/core/lib/diva_hacks/entity.rb
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+require_relative 'entity/basic_twitter_entity'
+require_relative 'entity/blank_entity'
+require_relative 'entity/extended_twitter_entity'
+require_relative 'entity/regexp_entity'
+require_relative 'entity/segment'
+require_relative 'entity/url_entity'
diff --git a/core/lib/retriever/entity/basic_twitter_entity.rb b/core/lib/diva_hacks/entity/basic_twitter_entity.rb
index 98e558bf..98e558bf 100644
--- a/core/lib/retriever/entity/basic_twitter_entity.rb
+++ b/core/lib/diva_hacks/entity/basic_twitter_entity.rb
diff --git a/core/lib/retriever/entity/blank_entity.rb b/core/lib/diva_hacks/entity/blank_entity.rb
index 1eb5ba0e..1eb5ba0e 100644
--- a/core/lib/retriever/entity/blank_entity.rb
+++ b/core/lib/diva_hacks/entity/blank_entity.rb
diff --git a/core/lib/retriever/entity/extended_twitter_entity.rb b/core/lib/diva_hacks/entity/extended_twitter_entity.rb
index 17ae4a75..17ae4a75 100644
--- a/core/lib/retriever/entity/extended_twitter_entity.rb
+++ b/core/lib/diva_hacks/entity/extended_twitter_entity.rb
diff --git a/core/lib/retriever/entity/regexp_entity.rb b/core/lib/diva_hacks/entity/regexp_entity.rb
index 6a4314be..6a4314be 100644
--- a/core/lib/retriever/entity/regexp_entity.rb
+++ b/core/lib/diva_hacks/entity/regexp_entity.rb
diff --git a/core/lib/retriever/entity/segment.rb b/core/lib/diva_hacks/entity/segment.rb
index 42313676..42313676 100644
--- a/core/lib/retriever/entity/segment.rb
+++ b/core/lib/diva_hacks/entity/segment.rb
diff --git a/core/lib/retriever/entity/url_entity.rb b/core/lib/diva_hacks/entity/url_entity.rb
index c24e7a68..c24e7a68 100644
--- a/core/lib/retriever/entity/url_entity.rb
+++ b/core/lib/diva_hacks/entity/url_entity.rb
diff --git a/core/lib/diva_hacks/mixin.rb b/core/lib/diva_hacks/mixin.rb
new file mode 100644
index 00000000..59fb2448
--- /dev/null
+++ b/core/lib/diva_hacks/mixin.rb
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+require_relative 'mixin/message_mixin'
+require_relative 'mixin/photo_mixin'
+require_relative 'mixin/user_mixin'
+
diff --git a/core/lib/retriever/mixin/message_mixin.rb b/core/lib/diva_hacks/mixin/message_mixin.rb
index e5a9bc79..e5a9bc79 100644
--- a/core/lib/retriever/mixin/message_mixin.rb
+++ b/core/lib/diva_hacks/mixin/message_mixin.rb
diff --git a/core/lib/retriever/mixin/photo_mixin.rb b/core/lib/diva_hacks/mixin/photo_mixin.rb
index 016766ba..016766ba 100644
--- a/core/lib/retriever/mixin/photo_mixin.rb
+++ b/core/lib/diva_hacks/mixin/photo_mixin.rb
diff --git a/core/lib/retriever/mixin/user_mixin.rb b/core/lib/diva_hacks/mixin/user_mixin.rb
index ce393a75..ce393a75 100644
--- a/core/lib/retriever/mixin/user_mixin.rb
+++ b/core/lib/diva_hacks/mixin/user_mixin.rb
diff --git a/core/lib/diva_hacks/model.rb b/core/lib/diva_hacks/model.rb
new file mode 100644
index 00000000..04e82f75
--- /dev/null
+++ b/core/lib/diva_hacks/model.rb
@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+require_relative 'model/identity'
+require_relative 'model/memory'
+
+module Mikutter::DivaHacks::Model
+ # Entityのリストを返す。
+ # ==== Return
+ # Retriever::Entity::BlankEntity
+ def links
+ @entity ||= self.class.entity_class.new(self)
+ end
+ alias :entity :links
+end
+
+module Mikutter::DivaHacks::ModelExtend
+ extend Gem::Deprecate
+ # Modelの情報を設定する。
+ # このメソッドを呼ぶと、他のプラグインがこのRetrieverを見つけることができるようになるので、
+ # 抽出タブの抽出条件が追加されたり、設定で背景色が指定できるようになる
+ # ==== Args
+ # [new_slug] Symbol
+ # [name:] String Modelの名前
+ # [reply:] bool このRetrieverに、宛先が存在するなら真
+ # [myself:] bool このRetrieverを、自分のアカウントによって作成できるなら真
+ # [timeline:] bool 真ならタイムラインに表示することができる
+ def register(new_slug,
+ name: new_slug.to_s,
+ reply: true,
+ myself: true,
+ timeline: false
+ )
+ @slug = new_slug.to_sym
+ spec = @spec = Diva::ModelSpec.new(@slug,
+ name.to_s.freeze,
+ !!reply,
+ !!myself,
+ !!timeline
+ ).freeze
+ plugin do
+ filter_retrievers do |retrievers|
+ retrievers << spec
+ [retrievers]
+ end
+ end
+ end
+
+ def plugin
+ if not @slug
+ raise Retriever::RetrieverError, "`#{self}'.slug is not set."
+ end
+ if block_given?
+ Plugin.create(:"retriever_model_#{@slug}", &Proc.new)
+ else
+ Plugin.create(:"retriever_model_#{@slug}")
+ end
+ end
+
+ # Entityクラスを設定する。
+ # ==== Args
+ # [klass] Class 新しく設定するEntityクラス
+ # ==== Return
+ # [Class] セットされた(されている)Entityクラス
+ def entity_class(klass=nil)
+ if klass
+ @entity_class = klass
+ else
+ @entity_class ||= Retriever::Entity::BlankEntity
+ end
+ end
+
+ # あるURIが、このModelを示すものであれば真を返す条件 _condition_ を設定する。
+ # _condition_ === uri が実行され、真を返せばそのURIをこのModelで取り扱えるということになる
+ # ==== Args
+ # [condition] 正規表現など、URIにマッチするもの
+ # ==== Return
+ # self
+ # ==== Block
+ # 実際にURIが指し示すリソースの内容を含んだModelを作って返す
+ # ===== Args
+ # [uri] URI マッチしたURI
+ # ===== Return
+ # [Delayer::Deferred::Deferredable]
+ # ネットワークアクセスを行って取得するなど取得に時間がかかる場合
+ # [self]
+ # すぐにModelを生成できる場合、そのModel
+ # ===== Raise
+ # [Retriever::ModelNotFoundError] _uri_ に対応するリソースが見つからなかった
+ def handle(condition) # :yield: uri
+ model_slug = self.slug
+ plugin do
+ if condition.is_a? Regexp
+ filter_model_of_uri do |uri, models|
+ if condition =~ uri.to_s
+ models << model_slug
+ end
+ [uri, models]
+ end
+ else
+ filter_model_of_uri do |uri, models|
+ if condition === uri
+ models << model_slug
+ end
+ [uri, models]
+ end
+ end
+ end
+ if block_given?
+ class << self
+ define_method(:find_by_uri, Proc.new)
+ end
+ end
+ end
+
+ # まだそのレコードのインスタンスがない場合、それを生成して返します。
+ def new_ifnecessary(hash)
+ type_strict hash => tcor(self, Hash)
+ result_strict(self) do
+ case hash
+ when self
+ hash
+ when Hash
+ self.new(hash)
+ else
+ raise ArgumentError.new("incorrect type #{hash.class} #{hash.inspect}")
+ end
+ end
+ end
+ #deprecate :new_ifnecessary, 'new', 2018, 2
+
+ def rewind(args)
+ type_strict args => Hash
+ result_strict(:merge){ new_ifnecessary(args) }.merge(args)
+ end
+ #deprecate :rewind, 'new', 2018, 2
+
+end
+
+module Diva
+ class Model
+ extend Mikutter::DivaHacks::ModelExtend
+ include Mikutter::DivaHacks::Model
+ end
+
+ RetrieverError = DivaError
+
+ deprecate_constant :RetrieverError
+end
diff --git a/core/lib/retriever/model/identity.rb b/core/lib/diva_hacks/model/identity.rb
index ead0e8d3..ead0e8d3 100644
--- a/core/lib/retriever/model/identity.rb
+++ b/core/lib/diva_hacks/model/identity.rb
diff --git a/core/lib/retriever/model/memory.rb b/core/lib/diva_hacks/model/memory.rb
index 299e44bc..299e44bc 100644
--- a/core/lib/retriever/model/memory.rb
+++ b/core/lib/diva_hacks/model/memory.rb
diff --git a/core/lib/retriever.rb b/core/lib/retriever.rb
index dc3cd86f..72453c4d 100644
--- a/core/lib/retriever.rb
+++ b/core/lib/retriever.rb
@@ -1,53 +1,50 @@
# -*- coding: utf-8 -*-
+require 'diva'
-module Retriever
+Retriever = Diva
+
+module Diva
# _model_slug_ をslugとして持つModelクラスを返す。
# 見つからない場合、nilを返す。
def self.Model(model_slug)
model_slug = model_slug.to_sym
- ObjectSpace.each_object(Retriever::Model.singleton_class) do |klass|
+ ObjectSpace.each_object(Diva::Model.singleton_class) do |klass|
return klass if klass.slug == model_slug
end
nil
end
- # _uri_ を Retriever::URI に変換する。
- # _uri_ が既に Retriever::URI のインスタンスだった場合は _uri_ を返すので、Retriever::URI
- # かもしれないオブジェクトを Retriever::URI に変換するのに使う。
+ # _uri_ を Diva::URI に変換する。
+ # _uri_ が既に Diva::URI のインスタンスだった場合は _uri_ を返すので、Diva::URI
+ # かもしれないオブジェクトを Diva::URI に変換するのに使う。
# ==== Args
# 以下のいずれかのクラスのインスタンス。
- # [Retriever::URI] _uri_ をそのまま返す
- # [URI::Generic] Retriever::URI.new(uri) の結果を返す
- # [Addressable::URI] Retriever::URI.new(uri) の結果を返す
- # [String] _uri_ をURI文字列と見立てて、 URI::Generic または Addressable::URI に変換して、 Retriever::URI のインスタンスを作る
- # [Hash] _uri_ を URI::Generic または Addressable::URI コンストラクタに渡して、URIを作り、 Retriever::URI のインスタンスを作る
+ # [Diva::URI] _uri_ をそのまま返す
+ # [URI::Generic] Diva::URI.new(uri) の結果を返す
+ # [Addressable::URI] Diva::URI.new(uri) の結果を返す
+ # [String] _uri_ をURI文字列と見立てて、 URI::Generic または Addressable::URI に変換して、 Diva::URI のインスタンスを作る
+ # [Hash] _uri_ を URI::Generic または Addressable::URI コンストラクタに渡して、URIを作り、 Diva::URI のインスタンスを作る
# ==== Returns
- # [Retriever::URI] 正しく変換できた
+ # [Diva::URI] 正しく変換できた
# [nil] _uri_ が不正
def self.URI(uri)
case uri
- when Retriever::URI
+ when Diva::URI
uri
when ::URI::Generic, Addressable::URI, String, Hash
- Retriever::URI.new(uri)
+ Diva::URI.new(uri)
end
end
# ==== Raises
- # [Retriever::InvalidURIError] _uri_ がURIではない場合
+ # [Diva::InvalidURIError] _uri_ がURIではない場合
def self.URI!(uri)
self.URI(uri) or raise InvalidURIError, "`#{uri.class}' is not uri."
end
end
-require_relative 'retriever/cast'
-require_relative 'retriever/datasource'
-require_relative 'retriever/error'
-require_relative 'retriever/model'
-require_relative 'retriever/field_generator'
-require_relative 'retriever/model/identity'
-require_relative 'retriever/model/memory'
-require_relative 'retriever/entity/blank_entity'
-require_relative 'retriever/entity/regexp_entity'
-require_relative 'retriever/entity/extended_twitter_entity'
-require_relative 'retriever/entity/url_entity'
+module Mikutter::DivaHacks; end
+
+require_relative 'diva_hacks/model'
+require_relative 'diva_hacks/mixin'
+require_relative 'diva_hacks/entity'
diff --git a/core/lib/retriever/cast.rb b/core/lib/retriever/cast.rb
deleted file mode 100644
index 5fb6f01f..00000000
--- a/core/lib/retriever/cast.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-module Retriever
- @@cast = {
- :int => lambda{ |v| begin v.to_i; rescue NoMethodError then raise InvalidTypeError end },
- :bool => lambda{ |v| !!(v and not v == 'false') },
- :string => lambda{ |v| begin v.to_s; rescue NoMethodError then raise InvalidTypeError end },
- :time => lambda{ |v|
- if not v then
- nil
- elsif v.is_a? String then
- Time.parse(v)
- else
- Time.at(v)
- end
- },
- :uri => lambda{ |v|
- Retriever::URI!(v)
- }
- }
-
- def self.cast_func(type)
- @@cast[type]
- end
-
-end
-
diff --git a/core/lib/retriever/datasource.rb b/core/lib/retriever/datasource.rb
deleted file mode 100644
index 633fac39..00000000
--- a/core/lib/retriever/datasource.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-
-=begin rdoc
-データの保存/復元を実際に担当するデータソース。
-データソースをモデルにModel::add_data_retrieverにて幾つでも参加させることが出来る。
-=end
-module Retriever::DataSource
- USE_ALL = -1 # findbyidの引数。全てのDataSourceから探索する
- USE_LOCAL_ONLY = -2 # findbyidの引数。ローカルにあるデータのみを使う
-
- attr_accessor :keys
-
- # idをもつデータを返す。
- # もし返せない場合は、nilを返す
- def findbyid(id, policy)
- nil
- end
-
- # 取得できたらそのRetrieverのインスタンスをキーにして実行されるDeferredを返す
- def idof(id)
- Thread.new{ findbyid(id) } end
- alias [] idof
-
- # データの保存
- # データ一件保存する。保存に成功したか否かを返す。
- def store_datum(datum)
- false
- end
-
- def inspect
- self.class.to_s
- end
-end
diff --git a/core/lib/retriever/error.rb b/core/lib/retriever/error.rb
deleted file mode 100644
index 76218a20..00000000
--- a/core/lib/retriever/error.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-module Retriever
- class RetrieverError < StandardError; end
-
- class InvalidTypeError < RetrieverError; end
-
- class InvalidEntityError < RetrieverError; end
-
- # 実装してもしなくてもいいメソッドが実装されておらず、結果を得られない
- class NotImplementedError < RetrieverError; end
-
- # IDやURIなどの一意にリソースを特定する情報を使ってデータソースに問い合わせたが、
- # 対応する情報が見つからず、Modelを作成できない
- class ModelNotFoundError < RetrieverError; end
-
- # URIとして受け付けられない値を渡された
- class InvalidURIError < InvalidTypeError; end
-
-end
diff --git a/core/lib/retriever/field_generator.rb b/core/lib/retriever/field_generator.rb
deleted file mode 100644
index 134f6218..00000000
--- a/core/lib/retriever/field_generator.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-
-class Retriever::FieldGenerator
- def initialize(model_klass)
- @model_klass = model_klass
- end
-
- def int(field_name, required: false)
- @model_klass.add_field(field_name, type: :int, required: required)
- end
-
- def string(field_name, required: false)
- @model_klass.add_field(field_name, type: :string, required: required)
- end
-
- def bool(field_name, required: false)
- @model_klass.add_field(field_name, type: :bool, required: required)
- end
-
- def time(field_name, required: false)
- @model_klass.add_field(field_name, type: :time, required: required)
- end
-
- def uri(field_name, required: false)
- @model_klass.add_field(field_name, type: :uri, required: required)
- end
-
- def has(field_name, type, required: false)
- @model_klass.add_field(field_name, type: type, required: required)
- end
-end
-
-
-
-
-
-
-
-
diff --git a/core/lib/retriever/model.rb b/core/lib/retriever/model.rb
deleted file mode 100644
index a9d6a5b6..00000000
--- a/core/lib/retriever/model.rb
+++ /dev/null
@@ -1,421 +0,0 @@
-# -*- coding: utf-8 -*-
-=begin rdoc
- いろんなリソースの基底クラス
-=end
-
-miquire :lib, 'typed-array'
-
-require_relative 'uri'
-require_relative 'spec'
-
-class Retriever::Model
- include Comparable
-
- class << self
- extend Gem::Deprecate
-
- attr_reader :slug, :spec
-
- # 新しいオブジェクトを生成します
- # 既にそのカラムのインスタンスが存在すればそちらを返します
- # また、引数のハッシュ値はmergeされます。
- def generate(args)
- return args if args.is_a?(self)
- self.new(args)
- end
-
- def rewind(args)
- type_strict args => Hash
- result_strict(:merge){ new_ifnecessary(args) }.merge(args)
- end
-
- # まだそのレコードのインスタンスがない場合、それを生成して返します。
- def new_ifnecessary(hash)
- type_strict hash => tcor(self, Hash)
- result_strict(self) do
- case hash
- when self
- hash
- when Hash
- self.new(hash)
- else
- raise ArgumentError.new("incorrect type #{hash.class} #{hash.inspect}") end end end
-
- # Modelのインスタンスのuriスキーム。オーバライドして適切な値にする
- # ==== Return
- # [String] URIスキーム
- memoize def scheme
- self.to_s.split('::',2).first.gsub(/\W/,'').downcase.freeze
- end
-
- # Modelのインスタンスのホスト名。オーバライドして適切な値にする
- # ==== Return
- # [String] ホスト名
- memoize def host
- self.to_s.split('::',2).last.split('::').reverse.join('.').gsub(/[^\w\.]/,'').downcase.freeze
- end
-
- # Modelにフィールド _field_name_ を追加する。
- # ==== Args
- # [field_name] Symbol フィールドの名前
- # [type] Symbol フィールドのタイプ。:int, :string, :bool, :time のほか、Retriever::Modelのサブクラスを指定する
- # [required] boolean _true_ なら、この項目を必須とする
- def add_field(field_name, type:, required: false)
- (@keys ||= []) << [field_name, type, required]
- case type
- when Symbol, Array
- define_method(field_name) do
- @value[field_name]
- end
- else
- define_method(field_name) do
- if @value[field_name].is_a? Retriever::Model
- @value[field_name]
- end
- end
-
- define_method("#{field_name}!") do
- mainthread_only
- if @value[field_name].is_a? Retriever::Model
- @value[field_name]
- else
- type.findbyid(@value[field_name], Retriever::DataSource::USE_ALL)
- end
- end
- end
-
- define_method("#{field_name}?") do
- !!@value[field_name]
- end
-
- define_method("#{field_name}=") do |value|
- @value[field_name] = Retriever::Model.cast(value, type, required)
- self.class.store_datum(self)
- value
- end
- self
- end
-
- def keys
- @keys end
-
- # Entityクラスを設定する。
- # ==== Args
- # [klass] Class 新しく設定するEntityクラス
- # ==== Return
- # [Class] セットされた(されている)Entityクラス
- def entity_class(klass=nil)
- if klass
- @entity_class = klass
- else
- @entity_class ||= Retriever::Entity::BlankEntity
- end
- end
-
- # srcが正常にModel化できるかどうかを返します。
- def valid?(src)
- return src.is_a?(self) if not src.is_a?(Hash)
- not self.get_error(src) end
-
- # srcがModel化できない理由を返します。
- def get_error(src)
- self.keys.each{ |column|
- key, type, required = *column
- begin
- Retriever::Model.cast(src[key], type, required)
- rescue Retriever::InvalidTypeError=>e
- return e.to_s + "\nin key '#{key}' value '#{src[key]}'" end }
- false end
-
- #
- # プライベートクラスメソッド
- #
-
- # Modelの情報を設定する。
- # このメソッドを呼ぶと、他のプラグインがこのRetrieverを見つけることができるようになるので、
- # 抽出タブの抽出条件が追加されたり、設定で背景色が指定できるようになる
- # ==== Args
- # [new_slug] Symbol
- # [name:] String Modelの名前
- # [reply:] bool このRetrieverに、宛先が存在するなら真
- # [myself:] bool このRetrieverを、自分のアカウントによって作成できるなら真
- # [timeline:] bool 真ならタイムラインに表示することができる
- def register(new_slug,
- name: new_slug.to_s,
- reply: true,
- myself: true,
- timeline: false
- )
- @slug = new_slug.to_sym
- spec = @spec = Retriever::ModelSpec.new(@slug,
- name.to_s.freeze,
- !!reply,
- !!myself,
- !!timeline
- ).freeze
- plugin do
- filter_retrievers do |retrievers|
- retrievers << spec
- [retrievers]
- end
- end
- end
-
- def field
- Retriever::FieldGenerator.new(self)
- end
-
- # あるURIが、このModelを示すものであれば真を返す条件 _condition_ を設定する。
- # _condition_ === uri が実行され、真を返せばそのURIをこのModelで取り扱えるということになる
- # ==== Args
- # [condition] 正規表現など、URIにマッチするもの
- # ==== Return
- # self
- # ==== Block
- # 実際にURIが指し示すリソースの内容を含んだModelを作って返す
- # ===== Args
- # [uri] URI マッチしたURI
- # ===== Return
- # [Delayer::Deferred::Deferredable]
- # ネットワークアクセスを行って取得するなど取得に時間がかかる場合
- # [self]
- # すぐにModelを生成できる場合、そのModel
- # ===== Raise
- # [Retriever::ModelNotFoundError] _uri_ に対応するリソースが見つからなかった
- def handle(condition) # :yield: uri
- model_slug = self.slug
- plugin do
- if condition.is_a? Regexp
- filter_model_of_uri do |uri, models|
- if condition =~ uri.to_s
- models << model_slug
- end
- [uri, models]
- end
- else
- filter_model_of_uri do |uri, models|
- if condition === uri
- models << model_slug
- end
- [uri, models]
- end
- end
- end
- if block_given?
- class << self
- define_method(:find_by_uri, Proc.new)
- end
- end
- end
-
- # URIに対応するリソースの内容を持ったModelを作成する。
- # URIに対応する情報はネットワーク上などから取得される場合もある。そういった場合はこのメソッドは
- # Delayer::Deferred::Deferredable を返す可能性がある。
- # このメソッドの振る舞いを変更したい場合は、 _handle_ メソッドを利用する。
- # ==== Args
- # [uri] _handle_ メソッドで指定したいずれかの条件に一致するURI
- # ==== Return
- # [Delayer::Deferred::Deferredable]
- # ネットワークアクセスを行って取得するなど取得に時間がかかる場合
- # [self]
- # すぐにModelを生成できる場合、そのModel
- # ==== Raise
- # [Retriever::NotImplementedError] _handle_ メソッドを一度もブロック付きで呼び出しておらず、Modelを取得できない
- # [Retriever::ModelNotFoundError] _uri_ に対応するリソースが見つからなかった
- def find_by_uri(uri)
- raise Retriever::NotImplementedError, "#{self}.find_by_uri does not implement."
- end
-
- def plugin
- if not @slug
- raise Retriever::RetrieverError, "`#{self}'.slug is not set."
- end
- if block_given?
- Plugin.create(:"retriever_model_#{@slug}", &Proc.new)
- else
- Plugin.create(:"retriever_model_#{@slug}")
- end
- end
-
- # Modelが生成・更新された時に呼ばれるコールバックメソッドです
- def store_datum(retriever); end
-
- # 値を、そのカラムの型にキャストします。
- # キャスト出来ない場合はInvalidTypeError例外を投げます
- def cast(value, type, required=false)
- if value.nil?
- raise Retriever::InvalidTypeError, 'it is required value'+[value, type, required].inspect if required
- nil
- elsif type.is_a?(Symbol)
- begin
- result = (value and Retriever::cast_func(type).call(value))
- if required and not result
- raise Retriever::InvalidTypeError, 'it is required value, but returned nil from cast function' end
- result
- rescue Retriever::InvalidTypeError
- raise Retriever::InvalidTypeError, "#{value.inspect} is not #{type}" end
- elsif type.is_a?(Array)
- if value.respond_to?(:map)
- value.map{|v| cast(v, type.first, required)}
- elsif not value
- nil
- else
- raise Retriever::InvalidTypeError, 'invalid type' end
- elsif value.is_a?(type)
- value
- elsif self.cast(value, type.keys.assoc(:id)[1], true)
- value end end
-
- memoize def container_class
- TypedArray(Retriever::Model) end
- end
-
- def initialize(args)
- type_strict args => Hash
- @value = args.dup
- validate
- self.class.store_datum(self)
- end
-
- # Entityのリストを返す。
- # ==== Return
- # Retriever::Entity::BlankEntity
- def links
- @entity ||= self.class.entity_class.new(self)
- end
- alias :entity :links
-
- # データをマージする。
- # selfにあってotherにもあるカラムはotherの内容で上書きされる。
- # 上書き後、データはDataSourceに保存される
- def merge(other)
- @value.update(other.to_hash)
- validate
- self.class.store_datum(self)
- end
-
- # このModelのパーマリンクを返す。
- # パーマリンクはWebのURLで、Web上のリソースでない場合はnilを返す。
- # ==== Return
- # 次のいずれか
- # [URI::HTTP] パーマリンク
- # [nil] パーマリンクが存在しない
- def perma_link
- nil
- end
-
- # このModelのURIを返す。
- # ==== Return
- # [URI::Generic|Retriever::URI] パーマリンク
- def uri
- perma_link || Retriever::URI.new("#{self.class.scheme}://#{self.class.host}#{path}")
- end
-
- # このRetrieverが、登録されているアカウントのうちいずれかが作成したものであれば true を返す
- # ==== Args
- # [service] Service | Enumerable 「自分」のService
- # ==== Return
- # [true] 自分のによって作られたオブジェクトである
- # [false] 自分のによって作られたオブジェクトではない
- def me?(service=nil)
- false end
-
- memoize def hash
- self.uri.to_s.hash ^ self.class.hash end
-
- def <=>(other)
- if other.is_a?(Retriever::Model)
- created - other.created
- elsif other.respond_to?(:[]) and other[:created]
- created - other[:created]
- else
- id - other end end
-
- def ==(other)
- if other.is_a? Retriever::Model
- self.class == other.class && uri == other.uri
- end
- end
-
- def eql?(other)
- self == other
- end
-
- def to_hash
- @value.dup
- end
-
- # カラムの生の内容を返す
- def fetch(key)
- @value[key.to_sym] end
- alias [] fetch
-
- # 速い順にcount個のRetrieverだけに問い合わせて返す
- def get(key, count=1)
- result = @value[key.to_sym]
- column = self.class.keys.assoc(key.to_sym)
- if column and result
- type = column[1]
- if type.is_a? Symbol
- Retriever::cast_func(type).call(result)
- elsif not result.is_a?(Retriever::Model::Identity)
- result = type.findbyid(result, count)
- if result
- return @value[key.to_sym] = result end end end
- result end
-
-
- # カラムに別の値を格納する。
- # 格納後、データはDataSourceに保存される
- def []=(key, value)
- @value[key.to_sym] = value
- self.class.store_datum(self)
- value end
-
- # カラムと型が違うものがある場合、例外を発生させる。
- def validate
- raise RuntimeError, "argument is #{@value}, not Hash" if not @value.is_a?(Hash)
- self.class.keys.each{ |column|
- key, type, required = *column
- begin
- @value[key.to_sym] = Retriever::Model.cast(self.fetch(key), type, required)
- rescue Retriever::InvalidTypeError=>e
- estr = e.to_s + "\nin #{self.fetch(key).inspect} of #{key}"
- warn estr
- warn @value.inspect
- raise Retriever::InvalidTypeError, estr end } end
-
- # キーとして定義されていない値を全て除外した配列を生成して返す。
- # また、Modelを子に含んでいる場合、それを外部キーに変換する。
- def filtering
- datum = self.to_hash
- result = Hash.new
- self.class.keys.each{ |column|
- key, type = *column
- begin
- result[key] = Retriever::Model.cast(datum[key], type)
- rescue Retriever::InvalidTypeError=>e
- raise Retriever::InvalidTypeError, e.to_s + "\nin #{datum.inspect} of #{key}" end }
- result end
-
- # このインスタンスのタイトル。
- def title
- fields = self.class.keys.select(&ret_nth(1))
- case
- when fields.include?(:name)
- name.gsub("\n", '')
- when fields.include?(:description)
- description.gsub("\n", '')
- else
- to_s.gsub("\n", '')
- end
- end
-
- private
- # URIがデフォルトで使うpath要素
- def path
- @path ||= "/#{SecureRandom.uuid}"
- end
-
-end
-
diff --git a/core/lib/retriever/spec.rb b/core/lib/retriever/spec.rb
deleted file mode 100644
index 1569dbfb..00000000
--- a/core/lib/retriever/spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-
-Retriever::ModelSpec = Struct.new(
- :slug,
- :name,
- :reply,
- :myself,
- :timeline,
-)
diff --git a/core/lib/retriever/uri.rb b/core/lib/retriever/uri.rb
deleted file mode 100644
index 8cfbe4ea..00000000
--- a/core/lib/retriever/uri.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-# -*- coding: utf-8 -*-
-
-=begin rdoc
-=Model用のURIクラス
-
-mikutterでは、 URI や Addressable::URI の代わりに、このクラスを使用します。
-URI や Addressable::URI に比べて、次のような特徴があります。
-
-* コンストラクタに文字列を渡している場合、 _to_s_ がその文字列を返す。
- * 正規化しないかわりに高速に動作します。
-* Retriever::URI のインスタンスは URI と同じように使える
-* unicode文字などが入っていて URI では表現できない場合、 Addressable::URI を使う
- * Addressable::URIでないと表現できないURIであればそちらを使うという判断を自動で行う
-
-== 使い方
-Retriever::URI() メソッドの引数にString, URI, Addressable::URI, Hash, Retriever::URIのいずれかを与えます。
-
-[String] uriの文字列(ex: "http://mikutter.hachune.net/")
-[URI] URI のインスタンス
-[Addressable::URI] Addressable::URI のインスタンス
-[Hash] これを引数にURI::Generic.build に渡すのと同じ形式の Hash
-[Retriever::URI] 即座にこれ自身を返す
-
-== 例
-
- Retriever::URI("http://mikutter.hachune.net/")
- Retriever::URI(URI::Generic.build(scheme: 'http', host: 'mikutter.hachune.net'))
-=end
-
-require 'uri'
-require 'addressable/uri'
-
-class Retriever::URI
- def initialize(uri)
- case uri.freeze
- when URI, Addressable::URI
- @uri = uri
- when String
- @uri_string = uri
- when Hash
- @uri_hash = uri
- end
- end
-
- def ==(other)
- case other
- when URI, Addressable::URI
- other == to_uri
- when Retriever::URI
- if has_string? or other.has_string?
- to_s == other.to_s
- else
- other.to_uri == to_uri
- end
- end
- end
-
- def hash
- to_s.hash ^ self.class.hash
- end
-
- def has_string?
- !!@uri_string
- end
-
- def has_uri?
- !!@uri
- end
-
- def to_s
- @uri_string ||= to_uri.to_s.freeze
- end
-
- def to_uri
- @uri ||= generate_uri.freeze
- end
-
- def scheme
- if has_string? and !has_uri?
- match = @uri_string.match(%r<\A(\w+):>)
- if match
- match[1]
- else
- to_uri.scheme
- end
- else
- to_uri.scheme
- end
- end
-
- def freeze
- unless frozen?
- to_uri
- to_s
- end
- super
- end
-
- def respond_to?(method)
- super or to_uri.respond_to?(method)
- end
-
- def method_missing(method, *rest, &block)
- to_uri.__send__(method, *rest, &block)
- end
-
- private
-
- def generate_uri
- if @uri
- @uri
- elsif @uri_string
- @uri = generate_uri_by_string
- elsif @uri_hash
- @uri = generate_uri_by_hash
- end
- @uri
- end
-
- def generate_uri_by_string
- URI.parse(@uri_string)
- rescue URI::InvalidComponentError
- Addressable::URI.parse(@uri_string)
- end
-
- def generate_uri_by_hash
- URI::Generic.build(@uri_hash)
- rescue URI::InvalidComponentError
- Addressable::URI.new(@uri_hash)
- end
-end
diff --git a/core/message.rb b/core/message.rb
index e28fed34..b851d0ad 100644
--- a/core/message.rb
+++ b/core/message.rb
@@ -273,10 +273,15 @@ class Message < Retriever::Model
# Message|nil リツイート元のMessage。リツイートではないならnil
def retweet_parent(force_retrieve=false)
if retweet?
- result = get(:retweet, (force_retrieve ? -1 : 1))
- if result.is_a?(Message)
- result.add_child(self) unless result.retweeted_statuses.include?(self)
- result end end end
+ case self[:retweet]
+ when Integer
+ self[:retweet] = Message.findbyid(retweet, force_retrieve ? -1 : 1) || self[:retweet]
+ when Message
+ self[:retweet].add_child(self) unless self[:retweet].retweeted_statuses.include?(self)
+ end
+ self[:retweet]
+ end
+ end
# retweet_parent の戻り値をnextに渡すDeferredableを返す
# ==== Args
@@ -561,7 +566,7 @@ class Message < Retriever::Model
end
def inspect
- @value.inspect
+ "#<#{self.class}: #{user.inspect}: #{description.inspect}>"
end
# Message#body と同じだが、投稿制限文字数を超えていた場合には、収まるように末尾を捨てる。
diff --git a/core/mui/gtk_photo_pixbuf.rb b/core/mui/gtk_photo_pixbuf.rb
index c36cce1c..b73e857b 100644
--- a/core/mui/gtk_photo_pixbuf.rb
+++ b/core/mui/gtk_photo_pixbuf.rb
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-miquire :lib, 'retriever/mixin/photo_mixin'
module Retriever::Model::PhotoMixin
diff --git a/core/plugin/activity/activity.rb b/core/plugin/activity/activity.rb
index a3420d67..65df7ddb 100644
--- a/core/plugin/activity/activity.rb
+++ b/core/plugin/activity/activity.rb
@@ -168,24 +168,25 @@ Plugin.create(:activity) do
# plugin, kind, title, icon, date, service
on_modify_activity do |params|
if not mute?(params)
- activity_view.scroll_to_zero_lator! if activity_view.realized? and activity_view.vadjustment.value == 0.0
- model = Plugin::Activity::Activity.new(params)
- next if @contains_uris.include?(model.uri)
- @contains_uris << model.uri
- iter = activity_view.model.prepend
+ params = params.dup
case params[:icon]
when GdkPixbuf::Pixbuf
- iter[ActivityView::ICON] = params[:icon]
- when Retriever::Model
- iter[ActivityView::ICON] = params[:icon].load_pixbuf(width: 24, height: 24){ |loaded_icon|
- iter[ActivityView::ICON] = loaded_icon
- }
- when nil, false
+ # TODO: Pixbufを渡された時の処理
+ params[:icon] = nil
+ when Retriever::Model, nil, false
+ # nothing to do
else
- photo = Enumerator.new{|y|
+ params[:icon] = Enumerator.new{|y|
Plugin.filtering(:photo_filter, params[:icon], y)
}.first
- iter[ActivityView::ICON] = photo.load_pixbuf(width: 24, height: 24){ |loaded_icon|
+ end
+ activity_view.scroll_to_zero_lator! if activity_view.realized? and activity_view.vadjustment.value == 0.0
+ model = Plugin::Activity::Activity.new(params)
+ next if @contains_uris.include?(model.uri)
+ @contains_uris << model.uri
+ iter = activity_view.model.prepend
+ if model.icon
+ iter[ActivityView::ICON] = model.icon.load_pixbuf(width: 24, height: 24){ |loaded_icon|
iter[ActivityView::ICON] = loaded_icon
}
end
diff --git a/core/plugin/activity/model/activity.rb b/core/plugin/activity/model/activity.rb
index 5d93319c..eb7e0a3e 100644
--- a/core/plugin/activity/model/activity.rb
+++ b/core/plugin/activity/model/activity.rb
@@ -9,7 +9,7 @@ module Plugin::Activity
field.string :description, required: true
field.string :title, required: true
- field.string :icon
+ field.has :icon, Diva::Model
field.bool :related
field.string :plugin_slug
field.time :date, required: true
diff --git a/core/plugin/core/core.rb b/core/plugin/core/core.rb
index c3fd7a8f..0d669554 100644
--- a/core/plugin/core/core.rb
+++ b/core/plugin/core/core.rb
@@ -75,7 +75,11 @@ Module.new do
@twitter_configuration = JSON.parse(file_get_contents(File.join(__dir__, 'configuration.json'.freeze)), symbolize_names: true)
onappear do |messages|
- retweets = messages.select(&:retweet?).map{|m|m.retweet_ancestors.to_a[-2]}
+ retweets = messages.select(&:retweet?).map do |message|
+ result = message.retweet_ancestors.to_a[-2]
+ fail "invalid retweet #{message.inspect}. ancestors: #{message.retweet_ancestors.to_a.inspect}" unless result.is_a?(Message)
+ result
+ end
if not(retweets.empty?)
Plugin.call(:retweet, retweets) end end
diff --git a/core/plugin/openimg/model/photo.rb b/core/plugin/openimg/model/photo.rb
index ab01e7c1..999b1731 100644
--- a/core/plugin/openimg/model/photo.rb
+++ b/core/plugin/openimg/model/photo.rb
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-miquire :lib, 'retriever/mixin/photo_mixin'
module Plugin::Openimg
class Photo < Retriever::Model
diff --git a/core/plugin/photo/model/photo.rb b/core/plugin/photo/model/photo.rb
index b954ead2..a260a645 100644
--- a/core/plugin/photo/model/photo.rb
+++ b/core/plugin/photo/model/photo.rb
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-miquire :lib, 'retriever/mixin/photo_mixin'
module Plugin::Photo
class Photo < Retriever::Model
diff --git a/core/plugin/skin/model/image.rb b/core/plugin/skin/model/image.rb
index 40bf747b..2efdab2f 100644
--- a/core/plugin/skin/model/image.rb
+++ b/core/plugin/skin/model/image.rb
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-miquire :lib, 'retriever/mixin/photo_mixin'
module Plugin::Skin
class Image < Retriever::Model
diff --git a/core/system/message.rb b/core/system/message.rb
index 26c8aadb..82e10d48 100644
--- a/core/system/message.rb
+++ b/core/system/message.rb
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
miquire :core, 'retriever', 'skin'
-miquire :lib, 'retriever/mixin/message_mixin'
class Mikutter::System::Message < Retriever::Model
include Retriever::Model::MessageMixin
diff --git a/core/system/user.rb b/core/system/user.rb
index 5a344f94..7c0cd607 100644
--- a/core/system/user.rb
+++ b/core/system/user.rb
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
miquire :core, 'retriever', 'skin'
-miquire :lib, 'retriever/mixin/user_mixin'
class Mikutter::System::User < Retriever::Model
include Retriever::Model::UserMixin
diff --git a/mikutter.rb b/mikutter.rb
index 28e78457..4d11fe13 100755
--- a/mikutter.rb
+++ b/mikutter.rb
@@ -12,6 +12,7 @@ http://opensource.org/licenses/mit-license.php
=end
mikutter_directory = File.expand_path(File.dirname(__FILE__))
+module Mikutter; end
if !ENV['DISABLE_BUNDLER_SETUP'] || ['', '0'].include?(ENV['DISABLE_BUNDLER_SETUP'].to_s)
begin
diff --git a/test/core/test_retriever.rb b/test/core/test_retriever.rb
deleted file mode 100644
index d866ff50..00000000
--- a/test/core/test_retriever.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-require File.expand_path(File.dirname(__FILE__) + '/../helper')
-# require File.expand_path(File.dirname(__FILE__) + '/../utils')
-miquire :core, 'retriever'
-
-class Message < Retriever::Model
- field.int :id, required: true
- field.string :title
- field.string :desc
- field.has :replyto, Message
- field.time :created
-
-end
-
-class TC_DataRetriever < Test::Unit::TestCase
-
- def test_generate
- a = Message.new_ifnecessary(:id => 1, :title => 'hello')
- assert_kind_of(Message, a)
- end
-
-end
-# >> Loaded suite -
-# >> Started
-# >> .
-# >> Finished in 0.000582 seconds.
-# >>
-# >> 1 tests, 1 assertions, 0 failures, 0 errors