aboutsummaryrefslogtreecommitdiffstats
path: root/core/plugin/display_requirements/display_requirements.rb
blob: 0909916e3455fb5b0e9f8d60fb51b9ec7640b6cb (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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# -*- coding: utf-8 -*-

Plugin.create :display_requirements do
  BIRD_URL = "http://mikutter.hachune.net/img/twitter-bird.png".freeze
  CACHE_DIR = File.expand_path(File.join(Environment::CACHE, 'dr'))
  BIRD_CACHE_PATH = File.join(CACHE_DIR, "twitter-bird.png")

  on_gui_timeline_join_tab do |i_timeline, i_tab|
    i_tab.shrink
    fuckingbird = Gtk::Button.new
    fuckingbird.relief = Gtk::RELIEF_NONE
    fuckingbird.add(Gtk::WebIcon.new(BIRD_URL, 32, 32))
    fuckingbird.ssc(:clicked){ Gtk.openurl("https://twitter.com/") }
    i_tab.nativewidget(fuckingbird)
    i_tab.expand
  end

  on_image_cache_saved do |url, imagedata|
    begin
      if BIRD_URL == url and not FileTest.exist?(BIRD_CACHE_PATH)
        FileUtils.mkdir_p(CACHE_DIR)
        file_put_contents BIRD_CACHE_PATH, imagedata
      end
    rescue => exception
      # ここにmikutterをクラッシュさせようとする厄介がおるじゃろ
      #   (^ω^)
      #  ⊃exception⊂
      #
      # こうして…
      #   (^ω^)
      #   ⊃cepti⊂
      #    :・..
      #
      # こうじゃ
      #   (^ω^)
      #    ⊃⊂
      #    :・:・
      #    ':.・..
      warn exception
    end
  end

  filter_image_cache do |url, image, &stop|
    if BIRD_URL == url and FileTest.exist?(BIRD_CACHE_PATH)
      stop.call([url, file_get_contents(BIRD_CACHE_PATH)]) end
    [url, image] end

  filter_entity_linkrule_added do |options|
    EventFilter.cancel! if :search_hashtag == options[:filter_id]
    [options] end

  Message::Entity.addlinkrule(:hashtags, /(?:#|#)[a-zA-Z0-9_]+/, :open_in_browser_hashtag){ |segment|
    Gtk.openurl("https://twitter.com/search/realtime?q="+CGI.escape(segment[:url].match(/\A(?:#|#)?.+\Z/)[0]))
  }

  # いいね
  filter_skin_get do |filename, fallback_dirs|
    case filename
    when 'fav.png'
      filename = 'like.png'
    when 'unfav.png'
      filename = 'dont_like.png' end
    [filename, fallback_dirs] end

  filter_command do |menu|
    menu.delete(:favorite)
    menu.delete(:delete_favorite)
    [menu]
  end

  command(:like,
          name: _('いいねいいねする'),
          condition: Plugin::Command[:CanFavoriteAny],
          visible: true,
          icon: Skin.get("dont_like.png"),
          role: :timeline) do |opt|
    opt.messages.select(&:favoritable?).reject{ |m| m.favorited_by_me? Service.primary }.each(&:favorite) end

  command(:delete_like,
          name: _('あんいいね'),
          condition: Plugin::Command[:IsFavoritedAll],
          visible: true,
          icon: Skin.get("like.png"),
          role: :timeline) do |opt|
    opt.messages.each(&:unfavorite) end

  defactivity :like, _("いいね")
  defactivity :dont_like, _("あんいいね")

  on_favorite do |service, user, message|
    activity(:like, "#{message.user[:idname]}: #{message.to_s}",
             description:(_("@%{user} がいいねいいねしました") % {user: user[:idname]} + "\n" +
                          "@#{message.user[:idname]}: #{message.to_s}\n"+
                          message.perma_link),
             icon: user[:profile_image_url],
             related: message.user.me? || user.me?,
             service: service)
  end

  on_unfavorite do |service, user, message|
    activity(:dont_like, "#{message.user[:idname]}: #{message.to_s}",
             description:(_("@%{user} があんいいねしました") % {user: user[:idname]} + "\n" +
                          "@#{message.user[:idname]}: #{message.to_s}\n"+
                          message.perma_link),
             icon: user[:profile_image_url],
             related: message.user.me? || user.me?,
             service: service)
  end

  filter_modify_activity do |options|
    if %i<favorite unfavorite>.include?(options[:kind])
      EventFilter.cancel!
    end
    [options]
  end

  filter_activity_kind do |activities|
    activities.delete(:favorite)
    activities.delete(:unfavorite)
    [activities]
  end

  # DR実績が解除されていたら差し戻す
  if defined?(UserConfig[:achievement_took].include?) and UserConfig[:achievement_took].include?(:display_requirements)
    UserConfig[:achievement_took] = UserConfig[:achievement_took].reject {|slug| :display_requirements == slug }
  end

  def rotten?
  end
end

class ::Gdk::MiraclePainter
  # 必ず名前のあとにスクリーンネームを表示しなければいけない。
  # また、スクリーンネームの前には必ず @ が必要。
  def header_left_markup
    Pango.parse_markup("<b>#{Pango.escape(message[:user][:name] || '')}</b> @#{Pango.escape(message[:user][:idname])}")
  end

  # 時刻の表記は必ず相対表記にしなければいけない。
  # ただし、規約には常に情報を更新し続けなければならないという文言はないので、
  # 表示の更新はとくにしない
  def timestamp_label
    now = Time.now.to_i
    there = message[:created].to_i
    diff = (there - now).abs
    label = case diff
            when 0
              Plugin[:display_requirements]._("今")
            when 1...60
              (there < now ? Plugin[:display_requirements]._("%{sec}秒前") : Plugin[:display_requirements]._("%{sec}秒後")) % {sec: diff}
            when 60...3600
              (there < now ? Plugin[:display_requirements]._('%{min}分前') : Plugin[:display_requirements]._('%{min}分後')) % {min: (diff/60).to_i}
            when 3600...86400
              (there < now ? Plugin[:display_requirements]._('%{hour}時間前') : Plugin[:display_requirements]._('%{hour}時間後')) % {hour: (diff/3600).to_i}
            else
              # TRANSLATORS: Time#strftimeが食う形式。
              # こんなん設定できたら良さそうだけどDRとかどうでもいいので適当にやってね
              message[:created].strftime(Plugin[:display_requirements]._('%Y/%m/%d'))
            end
    Pango.escape(label)end

  # アイコン上のボタンの数の変更
  def _schemer
    {x_count: 1, y_count: 1} end

  # アイコン上のボタンを削除
  def iob_icon_pixbuf
    [ [ nil ] ] end

  # アイコン上のボタンを削除
  def iob_icon_pixbuf_off
    [ [ nil] ] end

  # アイコンをクリックしたら必ずプロフィールを表示しなければならない
  def iob_clicked(gx, gy)
    if globalpos2iconpos(gx, gy)
      Plugin.call(:show_profile, Service.primary, message.user) end end

  # 名前からはプロフィールに、タイムスタンプからはツイートのパーマリンクにリンクしなければならない
  alias __clicked_l7eOfD__ clicked
  def clicked(x, y, e)
    if defined?(@hl_region) and @hl_region.point_in?(x, y)
      Plugin.call(:show_profile, Service.primary, message.user)
    elsif defined?(@hr_region) and @hr_region.point_in?(x, y)
      Gtk.openurl("https://twitter.com/#{message.user.idname}/status/#{message.id}")
    else
      __clicked_l7eOfD__(x, y, e)
    end
  end

end

class ::Gdk::SubPartsVoter
  # リツイートの表示は、必ず名前を表示しなければならない
  def render_user(context, user)
    render_icon(context, user)
    layout = context.create_pango_layout
    layout.wrap = Pango::WRAP_CHAR
    layout.font_description = Pango::FontDescription.new(UserConfig[:mumble_basic_font])
    layout.text = "#{user[:name]}"
    context.set_source_rgb(*(UserConfig[:mumble_basic_color] || [0,0,0]).map{ |c| c.to_f / 65536 })
    context.save{
      context.translate(0, (icon_height / 2) - (layout.size[1] / Pango::SCALE / 2))
      context.show_pango_layout(layout) }
    context.translate(layout.size[0] / Pango::SCALE + margin, 0)
    icon_width + layout.size[0] / Pango::SCALE + margin
  end
end