Repository: kastner/sin
Branch: master
Commit: 2237bb264f48
Files: 2
Total size: 6.3 KB
Directory structure:
gitextract_8zhzt0p5/
├── README
└── sinatra-blog.rb
================================================
FILE CONTENTS
================================================
================================================
FILE: README
================================================
Sin - The lazy Blogging engine in Sinatra
Based on a conversation with Dan Benjamin, I decided to see how hard it would be to get XMLRPC (MetaWeblog API) working on a minimal site.
As of right now (2008-02-17), it has:
* posting by anyone through MetaWeblog api (point blog editor at http://site/xml)
* uploads with the MetaWeblog api (only small-ish files, bug with Rack or something)
* hAtom
* A single file for the whole thing
================================================
FILE: sinatra-blog.rb
================================================
# Erik Kastner 2008-02-16 small blog engine with XMLRPC, hAtom and S3 upload (through xlmrpc) support
require 'rubygems'
require 'sinatra'
require 'xmlrpc/marshal'
require 'active_record'
require 'aws/s3'
BUCKET = "sinatra-data.metaatem.net"
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "sin.db")
begin
ActiveRecord::Schema.define do
create_table :posts do |t|
t.string :title
t.string :author
t.text :description
t.timestamps
end
end
rescue ActiveRecord::StatementInvalid
end
class Post < ActiveRecord::Base
def permalink; "/posts/#{to_param}"; end
def full_permalink; "http://sin.metaatem.net#{permalink}"; end
def to_metaweblog
{
:dateCreated => created_at,
:userid => 1,
:postid => id,
:description => description,
:title => title,
:link => "#{full_permalink}",
:permaLink => "#{full_permalink}",
:categories => ["General"],
:date_created_gmt => created_at.getgm,
}
end
end
# set utf-8 for outgoing
before_attend do
header "Content-Type" => "text/html; charset=utf-8"
end
layout do
<<-HTML
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Mini Sinatra Blog</title>
<link rel="alternate" href="feed://subtlety.errtheblog.com/O_o/2d4.xml" type="application/atom+xml"/>
<style type="text/css" media="screen">
body { font: 75% "Helvetica", arial, Verdana, sans-serif; background: #FFB03B; }
h1 { margin: 0; color: #8E2800; }
h2 { margin-bottom: 0;}
a { color: #468966; }
#page { margin: 1em auto; width: 41.667em; border: 0.75em solid #B64926; background: white; padding: 2em; }
.post { border-bottom: 0.4em double #FFB03B; padding-bottom: 1em;}
.post .subtitle { padding-bottom: 1em; font-size: 83.333%; display: block;}
#header, #footer { width: 47em; margin: 0 auto}
#header h3 { font-size: 320%; margin: 0.5em 0 0 0; font-family: "Georgia";}
#header h3 a { color: #FFF0A5; text-decoration: none; text-transform: uppercase; letter-spacing: 0.3em; text-shadow: #B64926 0.04em 0.04em;}
</style>
</head>
<body>
<div id="header"><h3><a href="/">Mini Blogin’</a></h3></div>
<div id="page">
<%= yield %>
</div>
<div id="footer">© Erik <a href="http://metaatem.net/" alt="kastner">Kastner</a>. Source code on <a href="http://pastie.textmate.org/153325" title="#153325 by Erik Kastner (kastner) - Pastie">pastie</a></div>
</body>
</html>
HTML
end
get '/' do
res = "<h1>Posts</h1>"
res += <<-HTML
<div class="post">
<p>Welcome. If you’d like to try adding a post. Point your editor at http://sin.metaatem.net/xml with any username.</p>
<p>You can even upload files. However, you can only upload small files until Rack, or Sinatra or SOMEONE fixes TempFile uploads.</p>
</div>
HTML
Post.find(:all, :limit => 20, :order => "created_at DESC").each do |p|
# hAtom
res << <<-HTML
<div class="post hentry">
<h2><a href="#{p.permalink}" class="entry-title" rel="bookmark">#{p.title}</a></h2>
<span class="subtitle">Posted by
<span class="author vcard fn">#{p.author}</span> on
<abbr class="updated" title="#{p.updated_at.getgm.strftime("%Y-%m-%dT%H:%M:%SZ")}">#{p.updated_at.strftime("%D")}</abbr>
</span>
<div class="content entry-content">
#{p.description}
</div>
</div>
HTML
end
erb res
end
# a single post -- sinatra doesn't do head requests in it's dsl yet. this is also DRY
%w{get head}.each do |meth|
Sinatra::Event.new(meth.to_sym, '/posts/:id') do
p = Post.find(params[:id])
res = "<h1>#{p.title}</h1>"
res << "#{p.updated_at.strftime("%D")}"
res << "<p>#{p.description}</p>"
erb res
end
end
# metaweblog api handler
post '/xml' do
xml = @request.env["rack.request.form_vars"]
if xml.empty?
hash = @request.env["rack.request.query_hash"]
xml = (hash.keys + hash.values).join
end
raise "Nothing supplied" if xml.empty?
call = XMLRPC::Marshal.load_call(xml)
# convert metaWeblog.getPost to get_post
method = call[0].gsub(/metaWeblog\.(.*)/, '\1').gsub(/([A-Z])/, '_\1').downcase
header 'Content-Type' => 'text/xml'
send(method, call)
end
def get_post(xmlrpc_call)
begin
post = Post.find(xmlrpc_call[1][0])
rescue ActiveRecord::RecordNotFound
post = Post.find(xmlrpc_call[1][0].gsub(/^.*posts\/(\d+)[^\d].*$/, '\1'))
end
XMLRPC::Marshal.dump_response(post.to_metaweblog)
end
def get_recent_posts(xmlrpc_call)
posts = Post.find(:all, :limit => 10, :order => "created_at DESC")
XMLRPC::Marshal.dump_response(posts.map{|p| p.to_metaweblog})
end
def new_post(xmlrpc_call)
data = xmlrpc_call[1]
# blog_id = data[0]; user = data[1]; pass = data[2]
post_data = data[3]
post = Post.create(:author => data[1], :title => post_data["title"], :description => post_data["description"])
XMLRPC::Marshal.dump_response(post.to_metaweblog)
end
def edit_post(xmlrpc_call)
data = xmlrpc_call[1]
post = Post.find(data[0])
# user = data[1]; pass = data[2]
post_data = data[3]
post.update_attributes!(:title => post_data["title"], :description => post_data["description"])
XMLRPC::Marshal.dump_response(post.to_metaweblog)
end
def get_categories(xmlrpc_call)
#res = [{ :categoryId => 1,:parentId => 0,:description => "General",:categoryName => "General",:htmlUrl => "http://test.com/categories/1",:rssUrl => "http://test.com/categories/1/feed"}]
XMLRPC::Marshal.dump_response(res)
end
def new_media_object(xmlrpc_call)
post_data = xmlrpc_call[1][3]
name = post_data["name"].gsub(/\//,'')
AWS::S3::Base.establish_connection!(
:access_key_id => ENV["AMAZON_ACCESS_KEY_ID"],
:secret_access_key => ENV["AMAZON_SECRET_ACCESS_KEY"]
)
AWS::S3::S3Object.store(name, post_data["bits"], BUCKET, :access => :public_read)
XMLRPC::Marshal.dump_response({
:file => name,
:url => "http://s3.amazonaws.com/#{BUCKET}/#{name}"
})
end
gitextract_8zhzt0p5/ ├── README └── sinatra-blog.rb
SYMBOL INDEX (10 symbols across 1 files)
FILE: sinatra-blog.rb
class Post (line 23) | class Post < ActiveRecord::Base
method permalink (line 24) | def permalink; "/posts/#{to_param}"; end
method full_permalink (line 25) | def full_permalink; "http://sin.metaatem.net#{permalink}"; end
method to_metaweblog (line 27) | def to_metaweblog
function get_post (line 135) | def get_post(xmlrpc_call)
function get_recent_posts (line 144) | def get_recent_posts(xmlrpc_call)
function new_post (line 149) | def new_post(xmlrpc_call)
function edit_post (line 157) | def edit_post(xmlrpc_call)
function get_categories (line 166) | def get_categories(xmlrpc_call)
function new_media_object (line 171) | def new_media_object(xmlrpc_call)
Condensed preview — 2 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7K chars).
[
{
"path": "README",
"chars": 438,
"preview": "Sin - The lazy Blogging engine in Sinatra\n\nBased on a conversation with Dan Benjamin, I decided to see how hard it would"
},
{
"path": "sinatra-blog.rb",
"chars": 6051,
"preview": "# Erik Kastner 2008-02-16 small blog engine with XMLRPC, hAtom and S3 upload (through xlmrpc) support\nrequire 'rubygems'"
}
]
About this extraction
This page contains the full source code of the kastner/sin GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 2 files (6.3 KB), approximately 2.1k tokens, and a symbol index with 10 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.