-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.rb
203 lines (185 loc) · 5.44 KB
/
server.rb
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
require 'sinatra'
require 'pry'
require './db/models.rb'
require './lib/scripts.rb'
configure :development do
Sinatra::Application.reset!
end
get '/' do
@tags = Tag.all.sort_by { |tag| tag.name.downcase }
@collections = Collection
.select("collections.*, COUNT(items_collections.id) AS items_count")
.left_joins(:items_collections)
.group("collections.id")
.sort_by { |collection| collection.name.downcase }
slim :index
end
get '/undirty_all' do
Scripts.undirty_all
redirect back
end
def standard_image_loader(collection, &blk)
if params[:media_type].present?
@media_type = params[:media_type]
collection = collection.where(media_type: params[:media_type])
end
@count = collection.count
if params[:random] == 'true'
@idx = rand(@count.to_i)
return redirect request.path + "?idx=#{@idx}&media_type=#{params[:media_type]}"
else
@idx = params[:idx].presence.to_i || 0
end
@item = collection.limit(1).offset(@idx).first
if @item
@tags = @item.tags
@collections = @item.collections
end
blk.call
end
get '/untagged' do
standard_image_loader(Item.left_outer_joins(:items_tags).where(items_tags: { id: nil })) do
slim :untagged
end
end
get '/no_collection' do
standard_image_loader(Item.left_outer_joins(:items_collections).where(items_collections: { id: nil })) do
slim :no_collection
end
end
get '/all' do
standard_image_loader(Item.all) do
slim :all
end
end
get '/tag/:name' do
@tag = Tag.find_by_name(params[:name])
standard_image_loader(@tag.items) do
slim :tag
end
end
get '/collection/:id' do
@collection = Collection.find(params[:id])
standard_image_loader(@collection.items) do
slim :collection
end
end
post '/bulk_modify_collection' do
operation, source_type, source_id, collection_name = params.values_at(
:operation, :source_type, :source_id, :collection
)
source_class = source_type == "tag" ? Tag : Collection
source = source_class.find(source_id.to_i)
collection = Collection.find_or_create_by(name: collection_name)
source.items.each do |item|
if operation == "add"
item.items_collections.find_or_create_by(collection: collection)
else
item.items_collections.find_by(collection: collection)&.destroy
end
end
if operation == "remove" && collection.items.none?
collection.destroy
if source == collection
return redirect '/'
end
end
redirect back
end
post '/bulk_modify_tag' do
operation, source_type, source_id, tag_name = params.values_at(
:operation, :source_type, :source_id, :tag
)
source_class = source_type == "tag" ? Tag : Collection
source = source_class.find(source_id.to_i)
tag = Tag.find_or_create_by(name: tag_name)
source.items.each do |item|
if operation == "add"
item.items_tags.find_or_create_by(tag: tag)
else
item.items_tags.find_by(tag: tag)&.destroy
end
end
if operation == "remove" && tag.items.none?
tag.destroy
if source == tag
return redirect '/'
end
end
redirect back
end
def send_video
file_size = File.size(@item.path)
content_type 'video/mp4'
headers "Accept-Ranges" => "bytes",
"Content-Length" => file_size.to_s
range_header = request.env["HTTP_RANGE"]
if range_header
range = range_header.split('bytes=')[1].split('-')
start_byte = range[0].to_i
end_byte = range[1] ? range[1].to_i : file_size - 1
headers "Content-Range" => "bytes #{start_byte}-#{end_byte}/#{file_size}",
"Content-Length" => (end_byte - start_byte + 1).to_s
status 206 # Partial Content
stream do |out|
File.open(@item.path, 'rb') do |file|
file.seek(start_byte)
out << file.read(end_byte - start_byte + 1)
end
end
else
status 200 # OK
stream do |out|
File.open(@item.path, 'rb') do |file|
out << file.read(1024) until file.eof?
end
end
end
end
get '/item/:id' do
@item = Item.find(params[:id])
return send_file(@item.path) unless @item.media_type == "video"
send_video
end
post '/item/:id/update' do
@item = Item.find(params[:id])
tag_names = params[:tags].split(" ").reject(&:blank?).map(&:strip)
tags_changed = @item.tags.pluck(:name).sort != tag_names.sort
if tags_changed
tag_names.each do |tag_name|
tag = Tag.find_or_create_by(name: tag_name)
@item.tags += [tag] unless @item.items_tags.exists?(tag: tag)
end
ItemsTag.transaction do
@item.tags.each do |tag|
unless tag_names.include?(tag.name)
@item.items_tags.find_by(tag: tag).destroy
unless ItemsTag.exists?(tag: tag)
tag.destroy
end
end
end
end
@item.update(dirty: true)
end
collection_names = params[:collections].split(" ").reject(&:blank?).map(&:strip)
collection_names.each do |collection_name|
collection = Collection.find_or_create_by(name: collection_name)
@item.collections += [collection] unless @item.items_collections.exists?(collection: collection)
end
@item.collections.each do |collection|
unless collection_names.include?(collection.name)
@item.items_collections.find_by(collection: collection).destroy
unless ItemsCollection.exists?(collection: collection)
collection.destroy
end
end
end
if params[:from_tag].present? && !Tag.exists?(name: params[:from_tag])
redirect '/'
elsif params[:from_collection].present? && !Collection.exists?(id: params[:from_collection])
redirect '/'
else
redirect back
end
end