@ -0,0 +1,13 @@ | |||
Mastodon | |||
======== | |||
Mastodon is a federated microblogging engine. An alternative implementation of the GNU Social project. Based on ActivityStreams, Webfinger, PubsubHubbub and Salmon. | |||
The core ideals of this project are: | |||
- Independence of legacy Twitter APIs - we don't want to be compatible with Twitter clients, we want our own clients | |||
- In that vein, a strong and clean REST API and OAuth2 | |||
- Minimalism. Just because you can do almost anything with ActivityStreams doesn't mean you should. Limit the set of possible functions to what makes sense in a microblogging engine. This will make federation as well as UI design a lot easier | |||
- Ease of deployment. The end-goal of this project is to be distributable as a Docker image. | |||
**Current status of the project is early development. Documentation, licensing information &co will be added later** |
@ -1,28 +0,0 @@ | |||
== README | |||
This README would normally document whatever steps are necessary to get the | |||
application up and running. | |||
Things you may want to cover: | |||
* Ruby version | |||
* System dependencies | |||
* Configuration | |||
* Database creation | |||
* Database initialization | |||
* How to run the test suite | |||
* Services (job queues, cache servers, search engines, etc.) | |||
* Deployment instructions | |||
* ... | |||
Please feel free to use a different markup language if you do not plan to run | |||
<tt>rake doc:app</tt>. |
@ -1,5 +1,101 @@ | |||
module AtomHelper | |||
def stream_updated_at | |||
@account.stream_entries.last ? @account.stream_entries.last.created_at.iso8601 : @account.updated_at.iso8601 | |||
@account.stream_entries.last ? @account.stream_entries.last.created_at : @account.updated_at | |||
end | |||
def entry(xml, is_root, &block) | |||
if is_root | |||
root_tag(xml, :entry, &block) | |||
else | |||
xml.entry &block | |||
end | |||
end | |||
def feed(xml, &block) | |||
root_tag(xml, :feed, &block) | |||
end | |||
def unique_id(xml, date, id, type) | |||
xml.id_ unique_tag(date, id, type) | |||
end | |||
def simple_id(xml, id) | |||
xml.id_ id | |||
end | |||
def published_at(xml, date) | |||
xml.published date.iso8601 | |||
end | |||
def updated_at(xml, date) | |||
xml.updated date.iso8601 | |||
end | |||
def verb(xml, verb) | |||
xml['activity'].send('verb', "http://activitystrea.ms/schema/1.0/#{verb}") | |||
end | |||
def content(xml, content) | |||
xml.content({ type: 'html' }, content) | |||
end | |||
def title(xml, title) | |||
xml.title title | |||
end | |||
def author(xml, &block) | |||
xml.author &block | |||
end | |||
def target(xml, &block) | |||
xml['activity'].object &block | |||
end | |||
def object_type(xml, type) | |||
xml['activity'].send('object-type', "http://activitystrea.ms/schema/1.0/#{type}") | |||
end | |||
def uri(xml, uri) | |||
xml.uri uri | |||
end | |||
def name(xml, name) | |||
xml.name name | |||
end | |||
def summary(xml, summary) | |||
xml.summary summary | |||
end | |||
def subtitle(xml, subtitle) | |||
xml.subtitle subtitle | |||
end | |||
def link_alternate(xml, url) | |||
xml.link(rel: 'alternate', type: 'text/html', href: url) | |||
end | |||
def link_self(xml, url) | |||
xml.link(rel: 'self', type: 'application/atom+xml', href: url) | |||
end | |||
def link_hub(xml, url) | |||
xml.link(rel: 'hub', href: url) | |||
end | |||
def link_salmon(xml, url) | |||
xml.link(rel: 'salmon', href: url) | |||
end | |||
def portable_contact(xml, account) | |||
xml['poco'].preferredUsername account.username | |||
xml['poco'].displayName account.display_name | |||
xml['poco'].note account.note | |||
end | |||
private | |||
def root_tag(xml, tag, &block) | |||
xml.send(tag, {xmlns: 'http://www.w3.org/2005/Atom', 'xmlns:thr': 'http://purl.org/syndication/thread/1.0', 'xmlns:activity': 'http://activitystrea.ms/spec/1.0/', 'xmlns:poco': 'http://portablecontacts.net/spec/1.0'}, &block) | |||
end | |||
end |
@ -1,39 +1,37 @@ | |||
Nokogiri::XML::Builder.new do |xml| | |||
xml.entry(xmlns: 'http://www.w3.org/2005/Atom', 'xmlns:thr': 'http://purl.org/syndication/thread/1.0', 'xmlns:activity': 'http://activitystrea.ms/spec/1.0/', 'xmlns:poco': 'http://portablecontacts.net/spec/1.0') do | |||
xml.id_ unique_tag(@entry.created_at, @entry.activity_id, @entry.activity_type) | |||
entry(xml, true) do | |||
unique_id xml, @entry.created_at, @entry.activity_id, @entry.activity_type | |||
published_at xml, @entry.activity.created_at | |||
updated_at xml, @entry.activity.updated_at | |||
title xml, @entry.title | |||
content xml, @entry.content | |||
verb xml, @entry.verb | |||
xml.published @entry.activity.created_at.iso8601 | |||
xml.updated @entry.activity.updated_at.iso8601 | |||
xml.title @entry.title | |||
xml.content({ type: 'html' }, @entry.content) | |||
xml['activity'].send('verb', "http://activitystrea.ms/schema/1.0/#{@entry.verb}") | |||
xml.author do | |||
xml['activity'].send('object-type', 'http://activitystrea.ms/schema/1.0/person') | |||
xml.uri profile_url(name: @entry.account.username) | |||
xml.name @entry.account.username | |||
xml.summary @entry.account.note | |||
xml.link(rel: 'alternate', type: 'text/html', href: profile_url(name: @entry.account.username)) | |||
xml['poco'].preferredUsername @entry.account.username | |||
xml['poco'].displayName @entry.account.display_name | |||
xml['poco'].note @entry.account.note | |||
author(xml) do | |||
object_type xml, :person | |||
uri xml, profile_url(name: @entry.account.username) | |||
name xml, @entry.account.username | |||
summary xml, @entry.account.note | |||
link_alternate xml, profile_url(name: @entry.account.username) | |||
portable_contact xml, @entry.account | |||
end | |||
if @entry.targeted? | |||
xml['activity'].send('object') do | |||
xml['activity'].send('object-type', "http://activitystrea.ms/schema/1.0/#{@entry.target.object_type}") | |||
xml.id_ @entry.target.uri | |||
xml.title @entry.target.title | |||
xml.summary @entry.target.summary | |||
xml.link(rel: 'alternate', type: 'text/html', href: @entry.target.uri) | |||
target(xml) do | |||
object_type xml, @entry.target.object_type | |||
simple_id xml, @entry.target.uri | |||
title xml, @entry.target.title | |||
summary xml, @entry.target.summary | |||
link_alternate xml, @entry.target.uri | |||
if @entry.target.object_type == :person | |||
portable_contact xml, @entry.target | |||
end | |||
end | |||
else | |||
xml['activity'].send('object-type', "http://activitystrea.ms/schema/1.0/#{@entry.object_type}") | |||
object_type xml, @entry.object_type | |||
end | |||
xml.link(rel: 'self', type: 'application/atom+xml', href: atom_entry_url(id: @entry.id)) | |||
link_self xml, atom_entry_url(id: @entry.id) | |||
end | |||
end.to_xml | |||
end |
@ -1,52 +1,49 @@ | |||
Nokogiri::XML::Builder.new do |xml| | |||
xml.feed(xmlns: 'http://www.w3.org/2005/Atom', 'xmlns:thr': 'http://purl.org/syndication/thread/1.0', 'xmlns:activity': 'http://activitystrea.ms/spec/1.0/', 'xmlns:poco': 'http://portablecontacts.net/spec/1.0') do | |||
xml.id_ atom_user_stream_url(id: @account.id) | |||
xml.title @account.display_name | |||
xml.subtitle @account.note | |||
xml.updated stream_updated_at | |||
xml.author do | |||
xml['activity'].send('object-type', 'http://activitystrea.ms/schema/1.0/person') | |||
xml.uri profile_url(name: @account.username) | |||
xml.name @account.username | |||
xml.summary @account.note | |||
xml.link(rel: 'alternate', type: 'text/html', href: profile_url(name: @account.username)) | |||
xml['poco'].preferredUsername @account.username | |||
xml['poco'].displayName @account.display_name | |||
xml['poco'].note @account.note | |||
feed(xml) do | |||
simple_id xml, atom_user_stream_url(id: @account.id) | |||
title xml, @account.display_name | |||
subtitle xml, @account.note | |||
updated_at xml, stream_updated_at | |||
author(xml) do | |||
object_type xml, :person | |||
uri xml, profile_url(name: @account.username) | |||
name xml, @account.username | |||
summary xml, @account.note | |||
link_alternate xml, profile_url(name: @account.username) | |||
portable_contact xml, @account | |||
end | |||
xml.link(rel: 'alternate', type: 'text/html', href: profile_url(name: @account.username)) | |||
xml.link(rel: 'hub', href: HUB_URL) | |||
xml.link(rel: 'salmon', href: salmon_url(@account)) | |||
xml.link(rel: 'self', type: 'application/atom+xml', href: atom_user_stream_url(id: @account.id)) | |||
link_alternate xml, profile_url(name: @account.username) | |||
link_self xml, atom_user_stream_url(id: @account.id) | |||
link_hub xml, HUB_URL | |||
link_salmon xml, salmon_url(@account) | |||
@account.stream_entries.order('id desc').each do |stream_entry| | |||
xml.entry do | |||
xml.id_ unique_tag(stream_entry.created_at, stream_entry.activity_id, stream_entry.activity_type) | |||
xml.published stream_entry.activity.created_at.iso8601 | |||
xml.updated stream_entry.activity.updated_at.iso8601 | |||
xml.title stream_entry.title | |||
xml.content({ type: 'html' }, stream_entry.content) | |||
xml['activity'].send('verb', "http://activitystrea.ms/schema/1.0/#{stream_entry.verb}") | |||
entry(xml, false) do | |||
unique_id xml, stream_entry.created_at, stream_entry.activity_id, stream_entry.activity_type | |||
published_at xml, stream_entry.activity.created_at | |||
updated_at xml, stream_entry.activity.updated_at | |||
title xml, stream_entry.title | |||
content xml, stream_entry.content | |||
verb xml, stream_entry.verb | |||
link_self xml, atom_entry_url(id: stream_entry.id) | |||
if stream_entry.targeted? | |||
xml['activity'].send('object') do | |||
xml['activity'].send('object-type', "http://activitystrea.ms/schema/1.0/#{stream_entry.target.object_type}") | |||
xml.id_ stream_entry.target.uri | |||
xml.title stream_entry.target.title | |||
xml.summary stream_entry.target.summary | |||
xml.link(rel: 'alternate', type: 'text/html', href: stream_entry.target.uri) | |||
target(xml) do | |||
object_type xml, stream_entry.target.object_type | |||
simple_id xml, stream_entry.target.uri | |||
title xml, stream_entry.target.title | |||
summary xml, stream_entry.target.summary | |||
link_alternate xml, stream_entry.target.uri | |||
if stream_entry.target.object_type == :person | |||
portable_contact xml, stream_entry.target | |||
end | |||
end | |||
else | |||
xml['activity'].send('object-type', "http://activitystrea.ms/schema/1.0/#{stream_entry.object_type}") | |||
object_type xml, stream_entry.object_type | |||
end | |||
xml.link(rel: 'self', type: 'application/atom+xml', href: atom_entry_url(id: stream_entry.id)) | |||
end | |||
end | |||
end | |||