+3
app/models/like.rb
+3
app/models/like.rb
+3
app/models/repost.rb
+3
app/models/repost.rb
+37
app/models/searchable.rb
+37
app/models/searchable.rb
···
1
+
require 'active_support/concern'
2
+
3
+
module Searchable
4
+
extend ActiveSupport::Concern
5
+
6
+
included do
7
+
scope :reverse_chronologically, -> { order(time: :desc, id: :desc) }
8
+
9
+
scope :after_cursor, ->(cursor) {
10
+
return self if cursor.nil?
11
+
12
+
t = arel_table
13
+
14
+
timestamp, id = cursor.split(':')
15
+
time = Time.at(timestamp.to_f)
16
+
17
+
where(
18
+
t[:time].lt(time)
19
+
.or(
20
+
t[:time].eq(time)
21
+
.and(t[:id].lt(id))
22
+
)
23
+
)
24
+
}
25
+
26
+
scope :matching_terms, ->(terms) {
27
+
where(
28
+
(["(posts.text ~* ?)"] * (terms.length)).join(" AND "),
29
+
*(terms.map { |x| "\\y#{x}\\y" })
30
+
)
31
+
}
32
+
33
+
def cursor
34
+
"#{self.time.to_f}:#{self.id}"
35
+
end
36
+
end
37
+
end
+24
-22
app/server.rb
+24
-22
app/server.rb
···
100
100
return json_error('UserNotFound', 'Missing authentication header') if user.nil?
101
101
end
102
102
103
-
if params[:query]
104
-
query = params[:query].gsub('%', "\\%")
105
-
words = query.strip.split(/ +/)
103
+
if params[:query].to_s.strip.empty?
104
+
return json_error('MissingParameter', 'Missing "query" parameter')
105
+
end
106
106
107
-
likes = user.likes
108
-
.joins(:post)
109
-
.includes(:post => :user)
110
-
.where(
111
-
(["(text ~* ?)"] * (words.length)).join(" AND "),
112
-
*(words.map { |x| "\\y#{x}\\y" })
113
-
)
114
-
.order('likes.time DESC, likes.id DESC')
115
-
.limit(PAGE_LIMIT)
116
-
117
-
if params[:cursor]
118
-
timestamp, id = params[:cursor].split(':')
119
-
time = Time.at(timestamp.to_f)
120
-
likes = likes.where("likes.time < ? OR (likes.time = ? AND likes.id < ?)", time, time, id)
121
-
end
107
+
if params[:collection].to_s.strip.empty?
108
+
return json_error('MissingParameter', 'Missing "collection" parameter')
109
+
end
122
110
123
-
post_uris = likes.map(&:post).map(&:at_uri)
111
+
query = params[:query].gsub('%', "\\%")
112
+
words = query.strip.split(/ +/)
124
113
125
-
json_response(posts: post_uris, cursor: likes.last && "#{likes.last.time.to_f}:#{likes.last.id}")
126
-
else
127
-
json_error('MissingParameter', 'Missing "query" parameter')
114
+
collection = case params[:collection]
115
+
when 'likes' then user.likes
116
+
when 'reposts' then user.reposts
117
+
else return json_error('InvalidParameter', 'Invalid search collection')
128
118
end
119
+
120
+
items = collection
121
+
.joins(:post)
122
+
.includes(:post => :user)
123
+
.matching_terms(words)
124
+
.reverse_chronologically
125
+
.after_cursor(params[:cursor])
126
+
.limit(PAGE_LIMIT)
127
+
128
+
post_uris = items.map(&:post).map(&:at_uri)
129
+
130
+
json_response(posts: post_uris, cursor: items.last&.cursor)
129
131
end
130
132
131
133
get '/.well-known/did.json' do