aboutsummaryrefslogtreecommitdiffstats
path: root/core/user.rb
blob: 7d247c8232cfa3f9e791502cb619b4070785d469 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# -*- coding: utf-8 -*-

miquire :core, 'retriever', 'skin'
miquire :system, 'system'
miquire :lib, 'typed-array'

class User < Retriever::Model
  extend Gem::Deprecate
  include Retriever::Model::Identity

  register :twitter_user, name: "Twitter User"

  # args format
  # key     | value
  # --------+-----------
  # id      | user id
  # idname  | account name
  # nickname| account usual name
  # location| location(not required)
  # detail  | detail
  # profile_image_url | icon

  field.string :id
  field.string :idname
  field.string :name
  field.string :location
  field.string :detail
  field.string :profile_image_url
  field.string :url
  field.bool   :protected
  field.bool   :verified
  field.int    :followers_count
  field.int    :statuses_count
  field.int    :friends_count

  handle %r[\Ahttps?://twitter.com/[a-zA-Z0-9_]+/?\Z] do |uri|
    match = %r[\Ahttps?://twitter.com/(?<screen_name>[a-zA-Z0-9_]+)/?\Z].match(uri.to_s)
    notice match.inspect
    if match
      user = findbyidname(match[:screen_name], Retriever::DataSource::USE_LOCAL_ONLY)
      if user
        user
      else
        Thread.new do
          findbyidname(match[:screen_name], Retriever::DataSource::USE_ALL)
        end
      end
    else
      raise Retriever::RetrieverError, "id##{match[:screen_name]} does not exist in #{self}."
    end
  end

  def self.system
    Mikutter::System::User.system end

  def self.memory
    @memory ||= UserMemory.new end

  def self.container_class
    Users end

  alias :to_i :id
  deprecate :to_i, "id", 2017, 05

  def idname
    self[:idname] end
  alias to_s idname

  def protected?
    !!self[:protected]
  end

  def verified?
    !!self[:verified]
  end

  # 大きいサイズのアイコンのURLを返す
  # ==== Return
  # 元のサイズのアイコンのURL
  def profile_image_url_large
    url = self[:profile_image_url]
    if url
      url.gsub(/_normal(.[a-zA-Z0-9]+)\Z/, '\1') end end

  def follow
    if(@value[:post]) then
      @value[:post].follow(self)
    end
  end

  def inspect
    "User(@#{@value[:idname]})"
  end

  # 投稿がシステムユーザだった場合にtrueを返す
  def system?
    false end

  def self.findbyidname(idname, count=Retriever::DataSource::USE_ALL)
    memory.findbyidname(idname, count) end

  def self.store_datum(datum)
    return datum if datum[:id][0] == '+'[0]
    super
  end

  def ==(other)
    if other.is_a?(String) then
      @value[:idname] == other
    elsif other.is_a?(User) then
      other[:id] == self[:id] end end

  # このUserオブジェクトが、登録されているアカウントのうちいずれかのものであるなら true を返す
  def me?(service = Service.instances)
    if service.is_a? Enumerable
      service.any?(&method(:me?))
    elsif service.is_a? Service
      service.user_obj == self end end

  # 互換性のため
  alias is_me? me?
  deprecate :is_me?, "me?", 2017, 05

  # :nodoc:
  def count_favorite_by
    Thread.new {raise RuntimeError, 'Favstar is dead.'} end
  deprecate :count_favorite_by, :none, 2017, 05


  # ユーザが今までにお気に入りにしたメッセージ数の概算を返す
  def count_favorite_given
    @value[:favourites_count] end

  memoize def perma_link
    URI.parse("https://twitter.com/#{idname}").freeze end

  def user
    self end
  alias to_user user

  def marshal_dump
    raise RuntimeError, 'User cannot marshalize'
  end

  class UserMemory < Retriever::Model::Memory
    def initialize
      super
      @idnames = {}             # idname => User
    end

    def findbyid(id, policy)
      result = super
      if !result and policy == Retriever::DataSource::USE_ALL
        if id.is_a? Enumerable
          id.each_slice(100).map{|id_list|
            Service.primary.scan(:user_lookup, id: id_list.join(','.freeze)) || [] }.flatten
        else
          Service.primary.scan(:user_show, id: id) end
      else
        result end end

    def findbyidname(idname, policy)
      if @idnames[idname.to_s]
        @idnames[idname.to_s]
      elsif policy == Retriever::DataSource::USE_ALL
        Service.primary.scan(:user_show, screen_name: idname)
      end
    end

    def store_datum(retriever)
      @idnames[retriever.idname.to_s] = retriever
      super
    end
  end

end

class Users < TypedArray(User)
end