mirror of
https://github.com/neocities/neocities.git
synced 2025-04-24 17:22:35 +02:00
api/info
This commit is contained in:
parent
7cd7973144
commit
d8da8de5b3
4 changed files with 127 additions and 32 deletions
89
app.rb
89
app.rb
|
@ -594,7 +594,7 @@ post '/api/upload' do
|
||||||
api_success 'your file(s) have been successfully uploaded'
|
api_success 'your file(s) have been successfully uploaded'
|
||||||
end
|
end
|
||||||
|
|
||||||
post '/api/:delete' do
|
post '/api/delete' do
|
||||||
require_api_credentials
|
require_api_credentials
|
||||||
|
|
||||||
api_error 'missing_filenames', 'you must provide files to delete' if params[:filenames].nil? || params[:filenames].empty?
|
api_error 'missing_filenames', 'you must provide files to delete' if params[:filenames].nil? || params[:filenames].empty?
|
||||||
|
@ -603,15 +603,15 @@ post '/api/:delete' do
|
||||||
|
|
||||||
params[:filenames].each do |filename|
|
params[:filenames].each do |filename|
|
||||||
unless filename.is_a?(String) && Site.valid_filename?(filename)
|
unless filename.is_a?(String) && Site.valid_filename?(filename)
|
||||||
api_error 'bad_filename', "#{filename} is not a valid filename, canceled all deletes"
|
api_error 'bad_filename', "#{filename} is not a valid filename, canceled deleting"
|
||||||
end
|
end
|
||||||
|
|
||||||
if !current_site.file_exists?(filename)
|
if !current_site.file_exists?(filename)
|
||||||
api_error 'missing_files', "#{filename} was not found on your site, canceled all deletes"
|
api_error 'missing_files', "#{filename} was not found on your site, canceled deleting"
|
||||||
end
|
end
|
||||||
|
|
||||||
if filename == 'index.html'
|
if filename == 'index.html'
|
||||||
api_error 'cannot_delete_index', 'you cannot delete your index.html file, canceled all deletes'
|
api_error 'cannot_delete_index', 'you cannot delete your index.html file, canceled deleting'
|
||||||
end
|
end
|
||||||
|
|
||||||
filenames << filename
|
filenames << filename
|
||||||
|
@ -621,7 +621,31 @@ post '/api/:delete' do
|
||||||
current_site.delete_file(filename)
|
current_site.delete_file(filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
api_success 'files have been deleted'
|
api_success 'file(s) have been deleted'
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/api/info' do
|
||||||
|
if params[:sitename]
|
||||||
|
site = Site[username: params[:sitename]]
|
||||||
|
api_error 'site_not_found', "could not find site #{params[:sitename]}" if site.nil?
|
||||||
|
api_success api_info_for(site)
|
||||||
|
else
|
||||||
|
init_api_credentials
|
||||||
|
api_success api_info_for(current_site)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def api_info_for(site)
|
||||||
|
{
|
||||||
|
info: {
|
||||||
|
sitename: site.username,
|
||||||
|
hits: site.hits,
|
||||||
|
created_at: site.created_at.rfc2822,
|
||||||
|
last_updated: site.updated_at.rfc2822,
|
||||||
|
domain: site.domain,
|
||||||
|
tags: site.tags.collect {|t| t.name}
|
||||||
|
}
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Catch-all for missing api calls
|
# Catch-all for missing api calls
|
||||||
|
@ -676,32 +700,45 @@ def encoding_fix(file)
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_api_credentials
|
def require_api_credentials
|
||||||
if auth = request.env['HTTP_AUTHORIZATION']
|
if !request.env['HTTP_AUTHORIZATION'].nil?
|
||||||
|
init_api_credentials
|
||||||
begin
|
|
||||||
user, pass = Base64.decode64(auth.match(/Basic (.+)/)[1]).split(':')
|
|
||||||
rescue
|
|
||||||
api_error_invalid_auth
|
|
||||||
end
|
|
||||||
|
|
||||||
if Site.valid_login? user, pass
|
|
||||||
site = Site[username: user]
|
|
||||||
|
|
||||||
if site.nil? || site.is_banned
|
|
||||||
api_error_invalid_auth
|
|
||||||
end
|
|
||||||
|
|
||||||
session[:id] = site.id
|
|
||||||
else
|
|
||||||
api_error_invalid_auth
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
api_error_invalid_auth
|
api_error_invalid_auth
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def api_success(message)
|
def init_api_credentials
|
||||||
halt({result: 'success', message: message}.to_json)
|
auth = request.env['HTTP_AUTHORIZATION']
|
||||||
|
|
||||||
|
begin
|
||||||
|
user, pass = Base64.decode64(auth.match(/Basic (.+)/)[1]).split(':')
|
||||||
|
rescue
|
||||||
|
api_error_invalid_auth
|
||||||
|
end
|
||||||
|
|
||||||
|
if Site.valid_login? user, pass
|
||||||
|
site = Site[username: user]
|
||||||
|
|
||||||
|
if site.nil? || site.is_banned
|
||||||
|
api_error_invalid_auth
|
||||||
|
end
|
||||||
|
|
||||||
|
session[:id] = site.id
|
||||||
|
else
|
||||||
|
api_error_invalid_auth
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def api_success(message_or_obj)
|
||||||
|
output = {result: 'success'}
|
||||||
|
|
||||||
|
if message_or_obj.is_a?(String)
|
||||||
|
output[:message] = message_or_obj
|
||||||
|
else
|
||||||
|
output.merge! message_or_obj
|
||||||
|
end
|
||||||
|
|
||||||
|
halt output.to_json
|
||||||
end
|
end
|
||||||
|
|
||||||
def api_error(error_type, message)
|
def api_error(error_type, message)
|
||||||
|
|
|
@ -73,10 +73,11 @@ class Site < Sequel::Model
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_tags=(tags_string)
|
def new_tags=(tags_string)
|
||||||
tags_string.gsub! /[^a-zA-Z0-9, ]/, ''
|
tags_string.gsub! ', ', ','
|
||||||
tags = tags_string.split ','
|
tags = tags_string.split ','
|
||||||
|
tags_string.gsub! /[^a-zA-Z0-9, ]/, ''
|
||||||
tags.collect! {|c| (c.match(/^\w+\s\w+/) || c.match(/^\w+/)).to_s }
|
tags.collect! {|c| (c.match(/^\w+\s\w+/) || c.match(/^\w+/)).to_s }
|
||||||
@new_tag_strings = tags
|
@new_tag_strings = tags.sort
|
||||||
end
|
end
|
||||||
|
|
||||||
def before_validation
|
def before_validation
|
||||||
|
|
|
@ -14,6 +14,45 @@ def create_site
|
||||||
@pass = site_attr[:password]
|
@pass = site_attr[:password]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'api info' do
|
||||||
|
it 'fails for no input' do
|
||||||
|
get '/api/info'
|
||||||
|
res[:error_type] = 'missing_sitename'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails for nonexistent site' do
|
||||||
|
get '/api/info', sitename: 'notexist'
|
||||||
|
res[:error_type].must_equal 'site_not_found'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'succeeds for valid sitename' do
|
||||||
|
create_site
|
||||||
|
@site.update hits: 31337, domain: 'derp.com', new_tags: 'derpie, man'
|
||||||
|
get '/api/info', sitename: @user
|
||||||
|
res[:result].must_equal 'success'
|
||||||
|
res[:info][:sitename].must_equal @site.username
|
||||||
|
res[:info][:hits].must_equal 31337
|
||||||
|
res[:info][:created_at].must_equal @site.created_at.rfc2822
|
||||||
|
res[:info][:last_updated].must_equal @site.updated_at.rfc2822
|
||||||
|
res[:info][:domain].must_equal 'derp.com'
|
||||||
|
res[:info][:tags].must_equal ['derpie', 'man']
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails for bad auth' do
|
||||||
|
basic_authorize 'derp', 'fake'
|
||||||
|
get '/api/info'
|
||||||
|
res[:error_type].must_equal 'invalid_auth'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'succeeds for api auth' do
|
||||||
|
create_site
|
||||||
|
@site.update hits: 12345
|
||||||
|
basic_authorize @user, @pass
|
||||||
|
get '/api/info'
|
||||||
|
res[:info][:hits] == 12345
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'api delete' do
|
describe 'api delete' do
|
||||||
it 'fails with no or bad auth' do
|
it 'fails with no or bad auth' do
|
||||||
post '/api/delete', filenames: ['hi.html']
|
post '/api/delete', filenames: ['hi.html']
|
||||||
|
|
|
@ -52,10 +52,10 @@ var NeoCities = require('neocities')
|
||||||
|
|
||||||
var api = new NeoCities('YOURUSERNAME', 'YOURPASSWORD')
|
var api = new NeoCities('YOURUSERNAME', 'YOURPASSWORD')
|
||||||
|
|
||||||
// Upload a file called local.html from your computer,
|
api.uploadFiles([{
|
||||||
// which will be named newfile.html on the site.
|
name: 'newfileonsite.html'
|
||||||
|
path: './local.html'
|
||||||
api.uploadFile('newfile.html', './local.html', function(resp) {
|
}], function(resp) {
|
||||||
if(resp.result == 'error')
|
if(resp.result == 'error')
|
||||||
throw new Error(resp.error_type+' - '+resp.message)
|
throw new Error(resp.error_type+' - '+resp.message)
|
||||||
|
|
||||||
|
@ -63,6 +63,10 @@ api.uploadFile('newfile.html', './local.html', function(resp) {
|
||||||
console.log(resp)
|
console.log(resp)
|
||||||
})
|
})
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3>POST /api/delete</h3>
|
<h3>POST /api/delete</h3>
|
||||||
<p>
|
<p>
|
||||||
|
@ -80,4 +84,18 @@ api.uploadFile('newfile.html', './local.html', function(resp) {
|
||||||
<code>
|
<code>
|
||||||
curl -d "filenames[]=img1.jpg" -d "filenames[]=img2.jpg" \<br> https://YOURUSER:YOURPASS@neocities.org/api/delete
|
curl -d "filenames[]=img1.jpg" -d "filenames[]=img2.jpg" \<br> https://YOURUSER:YOURPASS@neocities.org/api/delete
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
|
<h3>GET /api/info</h3>
|
||||||
|
<p>
|
||||||
|
This call lets you retreive information about a web site. This call does not require site authorization if you provide a <strong>sitename</strong> argument. Note that the sitename is the same as a username. If you provide auth credentials, you will receive the info for the auth user's site.
|
||||||
|
</p>
|
||||||
|
<h4>Examples</h4>
|
||||||
|
<h6>Using cURL</h6>
|
||||||
|
<code>
|
||||||
|
$ curl https://neocities.org/api/info?sitename=youpi
|
||||||
|
</code>
|
||||||
|
|
||||||
|
<code>
|
||||||
|
$ curl https://YOURUSER:YOURPASS@neocities.org/api/info
|
||||||
|
</code>
|
||||||
</div> <!-- end .content -->
|
</div> <!-- end .content -->
|
||||||
|
|
Loading…
Add table
Reference in a new issue