Compare commits

...

2 Commits
v1.2 ... master

Author SHA1 Message Date
byte-chan™ deeba9420f Fix /delete not deleting answers 2018-03-13 09:54:19 +01:00
byte-chan™ ae40be448e Code cleanup (#1) 2018-03-13 09:52:19 +01:00
2 changed files with 82 additions and 87 deletions

167
server.rb
View File

@ -7,8 +7,6 @@ require "sinatra"
require "json"
require_relative "sql"
set :bind, '0.0.0.0'
class String
def escape
self.gsub("&", "&amp;").gsub("<", "&lt;").gsub("\"", "&quot;")
@ -18,34 +16,7 @@ end
get "/" do
@title = PROJECT_DISPLAYNAME
@description = "Ask questions, copy link, get answers. Powered by Ruby, Sinatra and SQLite."
erb <<~BODY
<form id="f_question" action="/q" method="post"><div class="formdiv">
<input type="text" name="q_text" style="width: 100%; margin-bottom: 1em;" placeholder="Question"/>
<textarea name="q_options" style="width: 100%; height: 200px;" placeholder="Add answers here, one per line"></textarea>
<input type="submit" class="submit-main" value="Submit"/>
</div></form>
<h1>simplePoll</h1>
<p>simplePoll is a simple poll service powered by Ruby, Sinatra and SQLite. Static files are loaded into memory to improve performance. Using advanced IP address technology, users can only submit one answer for polls.</p>
<p>simplePoll also offers a simple API for poll information in JSON format:</p>
<pre>
/api/&lt;question_id&gt; =&gt; {
"id": question_id,
"text": "Question text",
"answers": [
{
"id": answer_id,
"text": "Answer 1",
"count": 3
},
{
"id": answer_id,
"text": "Answer 2"
"count": 37547821
}
]
}
</pre>
BODY
erb :home
end
get "/style.css" do
@ -53,14 +24,6 @@ get "/style.css" do
erb :style, layout: false
end
get "/error" do
raise Exception.new("OH NOES")
end
get "/secret" do
403
end
post "/q" do
text = params[:q_text]
options_raw = params[:q_options]
@ -68,27 +31,15 @@ post "/q" do
if not text or not options_raw then
status 400
@title = "Invalid input"
erb <<~BODY
<h1>Invalid input</h1>
<p>Missing POST data</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
BODY
erb :question_invalid
elsif text.size < 10 then
status 400
@title = "Invalid input"
erb <<~BODY
<h1>Invalid input</h1>
<p>Question too short</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
BODY
erb :question_short
elsif options.size < 2 then
status 400
@title = "Invalid input"
erb <<~BODY
<h1>Invalid input</h1>
<p>At least 2 answers required</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
BODY
erb :question_noanswers
else
q = new_question(text, options)
puts("Question #{q.id} created by #{request.ip.inspect}")
@ -145,7 +96,19 @@ get %r{/q/([0-9]+)/delete} do |id|
end
end
get %r{/q/([0-9]+)$} do |id|
get %r{/q/([0-9]+)/answer} do |id|
if question_exists? id.to_i then
if params["answer"] then
puts("Trying to submit answer for #{request.ip.inspect}")
Question.new(id.to_i).add_answer(request.ip, params["answer"])
end
redirect to "/q/#{id}"
else
404
end
end
get %r{/q/([0-9]+)} do |id|
if question_exists? id.to_i then
@q = Question.new(id.to_i)
@qdata = @q.summary
@ -161,36 +124,7 @@ get %r{/q/([0-9]+)$} do |id|
else
@delete_code = ""
end
erb <<~BODY
<form id="f_answer" action="/q/<%=@qdata[:id]%>/answer"><div class="formdiv">
<strong><%=@qdata[:text].escape%></strong>
<ul id="q_options"><% for opt in @qdata[:options] do %>
<li class="q_option">
<input type="radio" required id="radio<%= opt[:id] %>" name="answer" value="<%= opt[:id] %>"/><label for="radio<%= opt[:id] %>"><%= opt[:text].escape %></label><span style="float: right;"><%= opt[:count] %></span><br/>
<div class="q_answer_bar">
<div style="width: <%= @answer_count > 0 ? (opt[:count] / @answer_count.to_f)*100 : 0 %>%;"></div>
</div>
</li>
<% end %></ul>
<input type="submit" class="submit-main" value="Submit answer"/>
</div></form>
<form id="f_delete" action="/q/<%=@qdata[:id]%>/delete"><div class="formdiv">
<input type="text" size="32" name="code" placeholder="Code" value="#{@delete_code}"/>
<input type="submit" class="submit-delete" value="Delete"/>
</div></form>
BODY
else
404
end
end
get %r{/q/([0-9]+)/answer} do |id|
if question_exists? id.to_i then
if params["answer"] then
puts("Trying to submit answer for #{request.ip.inspect}")
Question.new(id.to_i).add_answer(request.ip, params["answer"])
end
redirect to "/q/#{id}"
erb :answer_form
else
404
end
@ -399,7 +333,7 @@ a.button:hover {
@@ e403
<h1>403 Forbidden</h1>
<p>You're doing this to yourself. Stop.</p>
<p>You do not have access to the requested location.</p>
@@ notfound
<h1>404 Not Found</h1>
@ -407,6 +341,67 @@ a.button:hover {
@@ e500
<h1>500 Internal Server Error</h1>
<p>This shouldn't've happened.</p>
<p>The server has encountered an error while processing your request.</p>
<p style="font-size: 50%;"><%= env["sinatra.error"].message %></p>
@@ question_invalid
<h1>Invalid input</h1>
<p>Missing POST data</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
@@ question_short
<h1>Invalid input</h1>
<p>Question too short</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
@@ question_noanswers
<h1>Invalid input</h1>
<p>At least 2 answers required</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
@@ home
<form id="f_question" action="/q" method="post"><div class="formdiv">
<input type="text" name="q_text" style="width: 100%; margin-bottom: 1em;" placeholder="Question"/>
<textarea name="q_options" style="width: 100%; height: 200px;" placeholder="Add answers here, one per line"></textarea>
<input type="submit" class="submit-main" value="Submit"/>
</div></form>
<h1>simplePoll</h1>
<p>simplePoll is a simple poll service powered by Ruby, Sinatra and SQLite. Static files are loaded into memory to improve performance. Using advanced IP address technology, users can only submit one answer for polls.</p>
<p>simplePoll also offers a simple API for poll information in JSON format:</p>
<pre>
/api/&lt;question_id&gt; =&gt; {
"success": true,
"id": question_id,
"text": "Question text",
"answers": [
{
"id": answer_id,
"text": "Answer 1",
"count": 3
},
{
"id": answer_id,
"text": "Answer 2"
"count": 37547821
}
]
}
</pre>
@@ answer_form
<form id="f_answer" action="/q/<%=@qdata[:id]%>/answer"><div class="formdiv">
<strong><%=@qdata[:text].escape%></strong>
<ul id="q_options"><% for opt in @qdata[:options] do %>
<li class="q_option">
<input type="radio" required id="radio<%= opt[:id] %>" name="answer" value="<%= opt[:id] %>"/><label for="radio<%= opt[:id] %>"><%= opt[:text].escape %></label><span style="float: right;"><%= opt[:count] %></span><br/>
<div class="q_answer_bar">
<div style="width: <%= @answer_count > 0 ? (opt[:count] / @answer_count.to_f)*100 : 0 %>%;"></div>
</div>
</li>
<% end %></ul>
<input type="submit" class="submit-main" value="Submit answer"/>
</div></form>
<form id="f_delete" action="/q/<%=@qdata[:id]%>/delete"><div class="formdiv">
<input type="text" size="32" name="code" placeholder="Code" value="<%= @delete_code %>"/>
<input type="submit" class="submit-delete" value="Delete"/>
</div></form>

2
sql.rb
View File

@ -101,7 +101,7 @@ end
def delete_question(id)
sql(<<~SQL, [id])
DELETE FROM q_answers WHERE q_answers.o_id IN (
DELETE FROM q_answers WHERE q_answers.id IN (
SELECT q_answers.id FROM q_options WHERE q_answers.o_id = q_options.id AND q_options.q_id = ?1
);
SQL