aboutsummaryrefslogtreecommitdiffstats
path: root/app/controllers/search_controller.rb
blob: 2777c0a9b9fa18bd186806f2b8a501863945e3dd (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
# -*- coding: utf-8 -*-
require "shellwords"

class SearchController < ApplicationController
  def search
    @show_search = true

    # TODO: OR とか () とか対応したいよね
    unless params[:query]
      render_tweets(Tweet.where(:id => -1))
      return
    end
    words = Shellwords.shellwords(params[:query])
    dateformat = "(20[0-9]{2})([-_\/]?)([0-9]{2})\\2([0-9]{2})" # $1: year, $3: month, $4: day

    result = words.inject(Tweet.order_by_id) do |tweets, word|
      case word
      when /^-?[a-z]+:.+$/
        # 特殊
        key, value = word.split(":", 2)
        case key.downcase
        when /^-?user$/
          user = User.cached(value)
          if key[0] == "-"
            tweets.where("user_id != ?", user ? user.id : -1)
          else
            tweets.where(:user_id => user ? user.id : -1)
          end
        when /^-?fav/
          search_unless_zero(tweets, "favorites_count", key[0], value)
        when /^-?re?t/
          search_unless_zero(tweets, "retweets_count", key[0], value)
        when /^-?reactions?$/
          search_unless_zero(tweets, "favorites_count + retweets_count", key[0], value)
        when "order"
          case value
          when "old", /^asc/
            tweets.order("id ASC")
          when "reaction"
            tweets.order_by_reactions
          when /^fav/
            tweets.order_by_favorites
          when /^re?t/
            tweets.order_by_retweets
          else
            tweets
          end
        when /^-?text$/
          sourcetext = word.split(":", 2).last.gsub("%", "\\%").gsub("*", "%")
          sourcetext = "%#{sourcetext}%".gsub(/%+/, "%")
          op = key[0] == "-" ? " NOT LIKE " : " LIKE "
          tweets.where("text #{op} ?", sourcetext)
        when /^-?source$/
          sourcetext = word.split(":", 2).last.gsub("%", "\\%").gsub("*", "%")
          op = key[0] == "-" ? " NOT LIKE " : " LIKE "
          tweets.where("source #{op} ? OR source #{op} ?", "<url:%:#{sourcetext.gsub(":", "%3A")}>", "<url:%:#{CGI.escape(sourcetext)}>")
        else
          # unknown command
          tweets
        end
      when /^-?#{dateformat}\.\.#{dateformat}$/

        since = Time.utc($1.to_i, $3.to_i, $4.to_i) - 9 * 60 * 60
        to = Time.utc($5.to_i, $7.to_i, $8.to_i + 1) - 9 * 60 * 60

        if word[0] == "-"
          tweets.where("id < ? OR id >= ?", first_id_of_time(since), first_id_of_time(to))
        else
          tweets.where(:id => first_id_of_time(since)...first_id_of_time(to))
        end
      else
        # TODO: ツイート検索
        tweets
      end
    end

    render_tweets(result)
  end

  private
  def first_id_of_time(time)
    p (time.to_i * 1000 - 1288834974657) << 22
  end

  def search_unless_zero(tweets, column, flag, value)
    num = Integer(value) rescue 0
    n = flag == "-"

    unless num == 0
      tweets.where("#{column}#{n ? "<" : ">="} ?", num)
    else
      tweets
    end
  end
end