Page MenuHomePhorge

No OneTemporary

Size
121 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/web/ostatus/handlers/note_handler.ex b/lib/pleroma/web/ostatus/handlers/note_handler.ex
index e67f67b37..f9aa463a0 100644
--- a/lib/pleroma/web/ostatus/handlers/note_handler.ex
+++ b/lib/pleroma/web/ostatus/handlers/note_handler.ex
@@ -1,103 +1,104 @@
defmodule Pleroma.Web.OStatus.NoteHandler do
require Logger
alias Pleroma.Web.{XML, OStatus}
alias Pleroma.{Object, User, Activity}
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.TwitterAPI
def fetch_replied_to_activity(entry, inReplyTo) do
if inReplyTo && !Object.get_cached_by_ap_id(inReplyTo) do
inReplyToHref = XML.string_from_xpath("//thr:in-reply-to[1]/@href", entry)
if inReplyToHref do
OStatus.fetch_activity_from_url(inReplyToHref)
else
Logger.debug("Couldn't find a href link to #{inReplyTo}")
end
end
end
@doc """
Get the context for this note. Uses this:
1. The context of the parent activity
2. The conversation reference in the ostatus xml
3. A newly generated context id.
"""
def get_context(entry, inReplyTo) do
context = (XML.string_from_xpath("//ostatus:conversation[1]", entry) || "") |> String.trim
with %{data: %{"context" => context}} <- Object.get_cached_by_ap_id(inReplyTo) do
context
else _e ->
if String.length(context) > 0 do
context
else
Utils.generate_context_id
end
end
end
def get_people_mentions(entry) do
:xmerl_xpath.string('//link[@rel="mentioned" and @ostatus:object-type="http://activitystrea.ms/schema/1.0/person"]', entry)
|> Enum.map(fn(person) -> XML.string_from_xpath("@href", person) end)
end
def get_collection_mentions(entry) do
transmogrify = fn
("http://activityschema.org/collection/public") ->
"https://www.w3.org/ns/activitystreams#Public"
(group) ->
group
end
:xmerl_xpath.string('//link[@rel="mentioned" and @ostatus:object-type="http://activitystrea.ms/schema/1.0/collection"]', entry)
|> Enum.map(fn(collection) -> XML.string_from_xpath("@href", collection) |> transmogrify.() end)
end
def get_mentions(entry) do
- get_people_mentions(entry)
- ++ get_collection_mentions(entry)
+ (get_people_mentions(entry)
+ ++ get_collection_mentions(entry))
+ |> Enum.filter(&(&1))
end
def make_to_list(actor, mentions) do
[
actor.follower_address
] ++ mentions
end
def add_external_url(note, entry) do
url = XML.string_from_xpath("//link[@rel='alternate' and @type='text/html']/@href", entry)
Map.put(note, "external_url", url)
end
def handle_note(entry, doc \\ nil) do
with id <- XML.string_from_xpath("//id", entry),
activity when is_nil(activity) <- Activity.get_create_activity_by_object_ap_id(id),
[author] <- :xmerl_xpath.string('//author[1]', doc),
{:ok, actor} <- OStatus.find_make_or_update_user(author),
content_html <- OStatus.get_content(entry),
inReplyTo <- XML.string_from_xpath("//thr:in-reply-to[1]/@ref", entry),
_inReplyToActivity <- fetch_replied_to_activity(entry, inReplyTo),
inReplyToActivity <- Activity.get_create_activity_by_object_ap_id(inReplyTo),
attachments <- OStatus.get_attachments(entry),
context <- get_context(entry, inReplyTo),
tags <- OStatus.get_tags(entry),
mentions <- get_mentions(entry),
to <- make_to_list(actor, mentions),
date <- XML.string_from_xpath("//published", entry),
note <- TwitterAPI.Utils.make_note_data(actor.ap_id, to, context, content_html, attachments, inReplyToActivity, []),
note <- note |> Map.put("id", id) |> Map.put("tag", tags),
note <- note |> Map.put("published", date),
note <- add_external_url(note, entry),
# TODO: Handle this case in make_note_data
note <- (if inReplyTo && !inReplyToActivity, do: note |> Map.put("inReplyTo", inReplyTo), else: note)
do
res = ActivityPub.create(to, actor, context, note, %{}, date, false)
User.update_note_count(actor)
res
else
%Activity{} = activity -> {:ok, activity}
e -> {:error, e}
end
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index dc66e27ad..de39834ca 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -1,317 +1,321 @@
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
alias Pleroma.{User, Activity, Repo, Object}
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
alias Pleroma.Web.TwitterAPI.UserView
alias Pleroma.Web.OStatus
alias Pleroma.Formatter
import Pleroma.Web.TwitterAPI.Utils
@httpoison Application.get_env(:pleroma, :httpoison)
def to_for_user_and_mentions(user, mentions, inReplyTo) do
default_to = [
user.follower_address,
"https://www.w3.org/ns/activitystreams#Public"
]
to = default_to ++ Enum.map(mentions, fn ({_, %{ap_id: ap_id}}) -> ap_id end)
if inReplyTo do
Enum.uniq([inReplyTo.data["actor"] | to])
else
to
end
end
def get_replied_to_activity(id) when not is_nil(id) do
Repo.get(Activity, id)
end
def get_replied_to_activity(_), do: nil
def create_status(%User{} = user, %{"status" => status} = data) do
with attachments <- attachments_from_ids(data["media_ids"]),
mentions <- Formatter.parse_mentions(status),
inReplyTo <- get_replied_to_activity(data["in_reply_to_status_id"]),
to <- to_for_user_and_mentions(user, mentions, inReplyTo),
content_html <- make_content_html(status, mentions, attachments),
context <- make_context(inReplyTo),
tags <- Formatter.parse_tags(status),
object <- make_note_data(user.ap_id, to, context, content_html, attachments, inReplyTo, tags) do
res = ActivityPub.create(to, user, context, object)
User.update_note_count(user)
res
end
end
def fetch_friend_statuses(user, opts \\ %{}) do
ActivityPub.fetch_activities([user.ap_id | user.following], opts)
|> activities_to_statuses(%{for: user})
end
def fetch_public_statuses(user, opts \\ %{}) do
opts = Map.put(opts, "local_only", true)
ActivityPub.fetch_public_activities(opts)
|> activities_to_statuses(%{for: user})
end
def fetch_public_and_external_statuses(user, opts \\ %{}) do
ActivityPub.fetch_public_activities(opts)
|> activities_to_statuses(%{for: user})
end
def fetch_user_statuses(user, opts \\ %{}) do
ActivityPub.fetch_activities([], opts)
|> activities_to_statuses(%{for: user})
end
def fetch_mentions(user, opts \\ %{}) do
ActivityPub.fetch_activities([user.ap_id], opts)
|> activities_to_statuses(%{for: user})
end
def fetch_conversation(user, id) do
with context when is_binary(context) <- conversation_id_to_context(id),
activities <- ActivityPub.fetch_activities_for_context(context),
statuses <- activities |> activities_to_statuses(%{for: user})
do
statuses
else _e ->
[]
end
end
def fetch_status(user, id) do
with %Activity{} = activity <- Repo.get(Activity, id) do
activity_to_status(activity, %{for: user})
end
end
def follow(%User{} = follower, params) do
with {:ok, %User{} = followed} <- get_user(params),
{:ok, follower} <- User.follow(follower, followed),
{:ok, activity} <- ActivityPub.follow(follower, followed)
do
{:ok, follower, followed, activity}
else
err -> err
end
end
def unfollow(%User{} = follower, params) do
with { :ok, %User{} = unfollowed } <- get_user(params),
{ :ok, follower, follow_activity } <- User.unfollow(follower, unfollowed),
{ :ok, _activity } <- ActivityPub.insert(%{
"type" => "Undo",
"actor" => follower.ap_id,
"object" => follow_activity.data["id"], # get latest Follow for these users
"published" => make_date()
})
do
{ :ok, follower, unfollowed }
else
err -> err
end
end
def favorite(%User{} = user, %Activity{data: %{"object" => object}} = activity) do
object = Object.get_by_ap_id(object["id"])
{:ok, _like_activity, object} = ActivityPub.like(user, object)
new_data = activity.data
|> Map.put("object", object.data)
status = %{activity | data: new_data}
|> activity_to_status(%{for: user})
{:ok, status}
end
def unfavorite(%User{} = user, %Activity{data: %{"object" => object}} = activity) do
object = Object.get_by_ap_id(object["id"])
{:ok, object} = ActivityPub.unlike(user, object)
new_data = activity.data
|> Map.put("object", object.data)
status = %{activity | data: new_data}
|> activity_to_status(%{for: user})
{:ok, status}
end
def retweet(%User{} = user, %Activity{data: %{"object" => object}} = activity) do
object = Object.get_by_ap_id(object["id"])
{:ok, _announce_activity, object} = ActivityPub.announce(user, object)
new_data = activity.data
|> Map.put("object", object.data)
status = %{activity | data: new_data}
|> activity_to_status(%{for: user})
{:ok, status}
end
def upload(%Plug.Upload{} = file, format \\ "xml") do
{:ok, object} = ActivityPub.upload(file)
url = List.first(object.data["url"])
href = url["href"]
type = url["mediaType"]
case format do
"xml" ->
# Fake this as good as possible...
"""
<?xml version="1.0" encoding="UTF-8"?>
<rsp stat="ok" xmlns:atom="http://www.w3.org/2005/Atom">
<mediaid>#{object.id}</mediaid>
<media_id>#{object.id}</media_id>
<media_id_string>#{object.id}</media_id_string>
<media_url>#{href}</media_url>
<mediaurl>#{href}</mediaurl>
<atom:link rel="enclosure" href="#{href}" type="#{type}"></atom:link>
</rsp>
"""
"json" ->
%{
media_id: object.id,
media_id_string: "#{object.id}}",
media_url: href,
size: 0
} |> Poison.encode!
end
end
def register_user(params) do
params = %{
nickname: params["nickname"],
name: params["fullname"],
bio: params["bio"],
email: params["email"],
password: params["password"],
password_confirmation: params["confirm"]
}
changeset = User.register_changeset(%User{}, params)
with {:ok, user} <- Repo.insert(changeset) do
{:ok, user}
else
{:error, changeset} ->
errors = Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
|> Poison.encode!
{:error, %{error: errors}}
end
end
def get_by_id_or_nickname(id_or_nickname) do
if !is_integer(id_or_nickname) && :error == Integer.parse(id_or_nickname) do
Repo.get_by(User, nickname: id_or_nickname)
else
Repo.get(User, id_or_nickname)
end
end
def get_user(user \\ nil, params) do
case params do
%{"user_id" => user_id} ->
case target = get_by_id_or_nickname(user_id) do
nil ->
{:error, "No user with such user_id"}
_ ->
{:ok, target}
end
%{"screen_name" => nickname} ->
case target = Repo.get_by(User, nickname: nickname) do
nil ->
{:error, "No user with such screen_name"}
_ ->
{:ok, target}
end
_ ->
if user do
{:ok, user}
else
{:error, "You need to specify screen_name or user_id"}
end
end
end
defp activities_to_statuses(activities, opts) do
Enum.map(activities, fn(activity) ->
activity_to_status(activity, opts)
end)
end
# For likes, fetch the liked activity, too.
defp activity_to_status(%Activity{data: %{"type" => "Like"}} = activity, opts) do
actor = get_in(activity.data, ["actor"])
user = User.get_cached_by_ap_id(actor)
[liked_activity] = Activity.all_by_object_ap_id(activity.data["object"])
ActivityRepresenter.to_map(activity, Map.merge(opts, %{user: user, liked_activity: liked_activity}))
end
# For announces, fetch the announced activity and the user.
defp activity_to_status(%Activity{data: %{"type" => "Announce"}} = activity, opts) do
actor = get_in(activity.data, ["actor"])
user = User.get_cached_by_ap_id(actor)
[announced_activity] = Activity.all_by_object_ap_id(activity.data["object"])
announced_actor = User.get_cached_by_ap_id(announced_activity.data["actor"])
ActivityRepresenter.to_map(activity, Map.merge(opts, %{users: [user, announced_actor], announced_activity: announced_activity}))
end
defp activity_to_status(activity, opts) do
actor = get_in(activity.data, ["actor"])
user = User.get_cached_by_ap_id(actor)
# mentioned_users = Repo.all(from user in User, where: user.ap_id in ^activity.data["to"])
mentioned_users = Enum.map(activity.data["to"] || [], fn (ap_id) ->
- User.get_cached_by_ap_id(ap_id)
+ if ap_id do
+ User.get_cached_by_ap_id(ap_id)
+ else
+ nil
+ end
end)
|> Enum.filter(&(&1))
ActivityRepresenter.to_map(activity, Map.merge(opts, %{user: user, mentioned: mentioned_users}))
end
defp make_date do
DateTime.utc_now() |> DateTime.to_iso8601
end
def context_to_conversation_id(context) do
with %Object{id: id} <- Object.get_cached_by_ap_id(context) do
id
else _e ->
changeset = Object.context_mapping(context)
case Repo.insert(changeset) do
{:ok, %{id: id}} -> id
# This should be solved by an upsert, but it seems ecto
# has problems accessing the constraint inside the jsonb.
{:error, _} -> Object.get_cached_by_ap_id(context).id
end
end
end
def conversation_id_to_context(id) do
with %Object{data: %{"id" => context}} <- Repo.get(Object, id) do
context
else _e ->
{:error, "No such conversation"}
end
end
def get_external_profile(for_user, uri) do
with {:ok, %User{} = user} <- OStatus.find_or_make_user(uri) do
with url <- user.info["topic"],
{:ok, %{body: body}} <- @httpoison.get(url, [], follow_redirect: true, timeout: 10000, recv_timeout: 20000) do
OStatus.handle_incoming(body)
end
{:ok, UserView.render("show.json", %{user: user, for: for_user})}
else _e ->
{:error, "Couldn't find user"}
end
end
end
diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex
index 7ae413c26..da38f662c 100644
--- a/lib/pleroma/web/web_finger/web_finger.ex
+++ b/lib/pleroma/web/web_finger/web_finger.ex
@@ -1,111 +1,125 @@
defmodule Pleroma.Web.WebFinger do
@httpoison Application.get_env(:pleroma, :httpoison)
alias Pleroma.{Repo, User, XmlBuilder}
alias Pleroma.Web
alias Pleroma.Web.{XML, Salmon, OStatus}
require Logger
def host_meta do
base_url = Web.base_url
{
:XRD, %{xmlns: "http://docs.oasis-open.org/ns/xri/xrd-1.0"},
{
:Link, %{rel: "lrdd", type: "application/xrd+xml", template: "#{base_url}/.well-known/webfinger?resource={uri}"}
}
}
|> XmlBuilder.to_doc
end
def webfinger(resource) do
host = Pleroma.Web.Endpoint.host
regex = ~r/(acct:)?(?<username>\w+)@#{host}/
with %{"username" => username} <- Regex.named_captures(regex, resource) do
user = User.get_by_nickname(username)
{:ok, represent_user(user)}
else _e ->
with user when not is_nil(user) <- User.get_cached_by_ap_id(resource) do
{:ok, represent_user(user)}
else _e ->
{:error, "Couldn't find user"}
end
end
end
def represent_user(user) do
{:ok, user} = ensure_keys_present(user)
{:ok, _private, public} = Salmon.keys_from_pem(user.info["keys"])
magic_key = Salmon.encode_key(public)
{
:XRD, %{xmlns: "http://docs.oasis-open.org/ns/xri/xrd-1.0"},
[
{:Subject, "acct:#{user.nickname}@#{Pleroma.Web.Endpoint.host}"},
{:Alias, user.ap_id},
{:Link, %{rel: "http://schemas.google.com/g/2010#updates-from", type: "application/atom+xml", href: OStatus.feed_path(user)}},
{:Link, %{rel: "http://webfinger.net/rel/profile-page", type: "text/html", href: user.ap_id}},
{:Link, %{rel: "salmon", href: OStatus.salmon_path(user)}},
{:Link, %{rel: "magic-public-key", href: "data:application/magic-public-key,#{magic_key}"}}
]
}
|> XmlBuilder.to_doc
end
# This seems a better fit in Salmon
def ensure_keys_present(user) do
info = user.info || %{}
if info["keys"] do
{:ok, user}
else
{:ok, pem} = Salmon.generate_rsa_pem
info = Map.put(info, "keys", pem)
Repo.update(Ecto.Changeset.change(user, info: info))
end
end
# FIXME: Make this call the host-meta to find the actual address.
defp webfinger_address(domain) do
"//#{domain}/.well-known/webfinger"
end
defp webfinger_from_xml(doc) do
magic_key = XML.string_from_xpath(~s{//Link[@rel="magic-public-key"]/@href}, doc)
"data:application/magic-public-key," <> magic_key = magic_key
topic = XML.string_from_xpath(~s{//Link[@rel="http://schemas.google.com/g/2010#updates-from"]/@href}, doc)
subject = XML.string_from_xpath("//Subject", doc)
salmon = XML.string_from_xpath(~s{//Link[@rel="salmon"]/@href}, doc)
data = %{
"magic_key" => magic_key,
"topic" => topic,
"subject" => subject,
"salmon" => salmon
}
{:ok, data}
end
- def finger(account, getter \\ &@httpoison.get/3) do
+ def get_template_from_xml(body) do
+ xpath = "//Link[@rel='lrdd' and @type='application/xrd+xml']/@template"
+ with doc when doc != :error <- XML.parse_document(body),
+ template when template != nil <- XML.string_from_xpath(xpath, doc) do
+ {:ok, template}
+ end
+ end
+
+ def find_lrdd_template(domain) do
+ with {:ok, %{status_code: status_code, body: body}} <- @httpoison.get("http://#{domain}/.well-known/host-meta", [], follow_redirect: true) do
+ get_template_from_xml(body)
+ else
+ e -> {:error, "Can't find lrdd template: #{inspect(e)}"}
+ end
+ end
+
+ def finger(account) do
domain = with [_name, domain] <- String.split(account, "@") do
domain
else _e ->
URI.parse(account).host
end
- address = webfinger_address(domain)
- # try https first
- response = with {:ok, result} <- getter.("https:" <> address, ["Accept": "application/xrd+xml"], [params: [resource: account]]) do
- {:ok, result}
- else _ ->
- getter.("http:" <> address, ["Accept": "application/xrd+xml"], [params: [resource: account], follow_redirect: true])
- end
+ {:ok, template} = find_lrdd_template(domain)
+
+ address = String.replace(template, "{uri}", URI.encode(account))
+
+ response = @httpoison.get(address, ["Accept": "application/xrd+xml"])
with {:ok, %{status_code: status_code, body: body}} when status_code in 200..299 <- response,
doc when doc != :error<- XML.parse_document(body),
{:ok, data} <- webfinger_from_xml(doc) do
{:ok, data}
else
e ->
Logger.debug(fn -> "Couldn't finger #{account}." end)
Logger.debug(fn -> inspect(e) end)
{:error, e}
end
end
end
diff --git a/test/fixtures/httpoison_mock/atarifrosch_feed.xml b/test/fixtures/httpoison_mock/atarifrosch_feed.xml
new file mode 100644
index 000000000..e00df782e
--- /dev/null
+++ b/test/fixtures/httpoison_mock/atarifrosch_feed.xml
@@ -0,0 +1,473 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:georss="http://www.georss.org/georss" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:media="http://purl.org/syndication/atommedia" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:statusnet="http://status.net/schema/api/1/">
+ <generator uri="https://gnu.io/social" version="1.2.0-alpha2">GNU social</generator>
+ <id>https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom</id>
+ <title>atarifrosch-Zeitleiste</title>
+ <subtitle>Aktualisierungen von atarifrosch auf social.stopwatchingus-heidelberg.de!</subtitle>
+ <logo>https://social.stopwatchingus-heidelberg.de/avatar/18330-96-20150628163706.png</logo>
+ <updated>2017-08-24T12:06:55+02:00</updated>
+<author>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
+ <uri>https://social.stopwatchingus-heidelberg.de/user/18330</uri>
+ <name>atarifrosch</name>
+ <summary>Nerd, Pirat, Debian user, CAcert assurer, Geocacher, Freifunker. Autismus/Depression, agender. GnuPG Key-ID: 0xBCF81ADE</summary>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/atarifrosch"/>
+ <link rel="avatar" type="image/png" media:width="480" media:height="480" href="https://social.stopwatchingus-heidelberg.de/avatar/18330-480-20150628163705.png"/>
+ <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://social.stopwatchingus-heidelberg.de/avatar/18330-96-20150628163706.png"/>
+ <link rel="avatar" type="image/png" media:width="48" media:height="48" href="https://social.stopwatchingus-heidelberg.de/avatar/18330-48-20150628163713.png"/>
+ <link rel="avatar" type="image/png" media:width="24" media:height="24" href="https://social.stopwatchingus-heidelberg.de/avatar/18330-24-20150628163714.png"/>
+ <poco:preferredUsername>atarifrosch</poco:preferredUsername>
+ <poco:displayName>Atari-Frosch</poco:displayName>
+ <poco:note>Nerd, Pirat, Debian user, CAcert assurer, Geocacher, Freifunker. Autismus/Depression, agender. GnuPG Key-ID: 0xBCF81ADE</poco:note>
+ <poco:address>
+ <poco:formatted>Düsseldorf, NRW, Germany</poco:formatted>
+ </poco:address>
+ <poco:urls>
+ <poco:type>homepage</poco:type>
+ <poco:value>https://www.atari-frosch.de/</poco:value>
+ <poco:primary>true</poco:primary>
+ </poco:urls>
+ <followers url="https://social.stopwatchingus-heidelberg.de/atarifrosch/subscribers"></followers>
+ <statusnet:profile_info local_id="18330"></statusnet:profile_info>
+</author>
+ <link href="https://social.stopwatchingus-heidelberg.de/atarifrosch" rel="alternate" type="text/html"/>
+ <link href="https://social.stopwatchingus-heidelberg.de/main/sup" rel="http://api.friendfeed.com/2008/03#sup" type="application/json"/>
+ <link href="https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom?max_id=976980" rel="next" type="application/atom+xml"/>
+ <link href="https://social.stopwatchingus-heidelberg.de/main/push/hub" rel="hub"/>
+ <link href="https://social.stopwatchingus-heidelberg.de/main/salmon/user/18330" rel="salmon"/>
+ <link href="https://social.stopwatchingus-heidelberg.de/main/salmon/user/18330" rel="http://salmon-protocol.org/ns/salmon-replies"/>
+ <link href="https://social.stopwatchingus-heidelberg.de/main/salmon/user/18330" rel="http://salmon-protocol.org/ns/salmon-mention"/>
+ <link href="https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom" rel="self" type="application/atom+xml"/>
+<entry>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-24:noticeId=978735:objectType=note</id>
+ <title>atarifrosch repeated a notice by hoergen</title>
+ <content type="html">RT @&lt;a href=&quot;https://social.hoergen.org/hoergen&quot; class=&quot;h-card mention&quot; title=&quot;hoergen&quot;&gt;hoergen&lt;/a&gt; Das falsche Bild der Tagesschau &amp;quot;Auffallend &amp;quot;erfolgreich&amp;quot; - Andrea Nahles und Manuela Schwesig&amp;quot; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.stopwatchingus-heidelberg.de/tag/geringverdiener&quot; rel=&quot;tag&quot;&gt;Geringverdiener&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.stopwatchingus-heidelberg.de/tag/mindestlohn&quot; rel=&quot;tag&quot;&gt;Mindestlohn&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.stopwatchingus-heidelberg.de/tag/mannxismus&quot; rel=&quot;tag&quot;&gt;mannxismus&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.stopwatchingus-heidelberg.de/tag/erwerbsminderungsrente&quot; rel=&quot;tag&quot;&gt;Erwerbsminderungsrente&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.stopwatchingus-heidelberg.de/tag/arbeitnehmerflexibilisierung&quot; rel=&quot;tag&quot;&gt;ArbeitnehmerFlexibilisierung&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.stopwatchingus-heidelberg.de/tag/altersarmut&quot; rel=&quot;tag&quot;&gt;AltersArmut&lt;/a&gt;&lt;/span&gt; ..... &lt;a href=&quot;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&quot; title=&quot;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&quot; class=&quot;attachment&quot; id=&quot;attachment-450858&quot; rel=&quot;nofollow external&quot;&gt;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&lt;/a&gt;</content>
+ <link rel="alternate" type="text/html">https://social.stopwatchingus-heidelberg.de/notice/978735</link>
+ <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb>
+ <published>2017-08-24T09:18:25+00:00</published>
+ <updated>2017-08-24T09:18:25+00:00</updated>
+ <activity:object>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type>
+ <id>tag:social.hoergen.org,2017-08-24:noticeId=222320:objectType=note</id>
+ <title></title>
+ <content type="html">Das falsche Bild der Tagesschau &lt;br /&gt; &amp;quot;Auffallend &amp;quot;erfolgreich&amp;quot; - Andrea Nahles und Manuela Schwesig&amp;quot; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/geringverdiener&quot; rel=&quot;tag&quot;&gt;Geringverdiener&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/mindestlohn&quot; rel=&quot;tag&quot;&gt;Mindestlohn&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/mannxismus&quot; rel=&quot;tag&quot;&gt;mannxismus&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/erwerbsminderungsrente&quot; rel=&quot;tag&quot;&gt;Erwerbsminderungsrente&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/arbeitnehmerflexibilisierung&quot; rel=&quot;tag&quot;&gt;ArbeitnehmerFlexibilisierung&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/altersarmut&quot; rel=&quot;tag&quot;&gt;AltersArmut&lt;/a&gt;&lt;/span&gt; ..... &lt;br /&gt; &lt;br /&gt; &lt;a href=&quot;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&quot; title=&quot;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot;&gt;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&lt;/a&gt;</content>
+ <link rel="alternate" type="text/html">https://social.hoergen.org/notice/222320</link>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-24T07:36:31+00:00</published>
+ <updated>2017-08-24T07:36:31+00:00</updated>
+ <author>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
+ <uri>https://social.hoergen.org/user/2</uri>
+ <name>hoergen</name>
+ <summary>aka Andi Memyself #humanist #nerd Menschen liebhabender Misanthrop und auch sonst sehr vielseitig interessiert.</summary>
+ <link rel="alternate" type="text/html" href="https://social.hoergen.org/hoergen"/>
+ <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.stopwatchingus-heidelberg.de/avatar/54316-original-20170824072526.jpeg"/>
+ <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.stopwatchingus-heidelberg.de/avatar/54316-original-20170824072526.jpeg"/>
+ <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.stopwatchingus-heidelberg.de/avatar/54316-48-20170824072544.jpeg"/>
+ <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.stopwatchingus-heidelberg.de/avatar/54316-24-20170824074851.jpeg"/>
+ <poco:preferredUsername>hoergen</poco:preferredUsername>
+ <poco:displayName>hoergen</poco:displayName>
+ <poco:note>aka Andi Memyself #humanist #nerd Menschen liebhabender Misanthrop und auch sonst sehr vielseitig interessiert.</poco:note>
+ <poco:address>
+ <poco:formatted>Berlin</poco:formatted>
+ </poco:address>
+ <poco:urls>
+ <poco:type>homepage</poco:type>
+ <poco:value>https://hyperblog.de/hoergen/</poco:value>
+ <poco:primary>true</poco:primary>
+ </poco:urls>
+ <statusnet:profile_info local_id="54316"></statusnet:profile_info>
+ </author>
+ <activity:object>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.hoergen.org,2017-08-24:noticeId=222320:objectType=note</id>
+ <title>New note by hoergen</title>
+ <content type="html">Das falsche Bild der Tagesschau &lt;br /&gt; &amp;quot;Auffallend &amp;quot;erfolgreich&amp;quot; - Andrea Nahles und Manuela Schwesig&amp;quot; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/geringverdiener&quot; rel=&quot;tag&quot;&gt;Geringverdiener&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/mindestlohn&quot; rel=&quot;tag&quot;&gt;Mindestlohn&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/mannxismus&quot; rel=&quot;tag&quot;&gt;mannxismus&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/erwerbsminderungsrente&quot; rel=&quot;tag&quot;&gt;Erwerbsminderungsrente&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/arbeitnehmerflexibilisierung&quot; rel=&quot;tag&quot;&gt;ArbeitnehmerFlexibilisierung&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.hoergen.org/tag/altersarmut&quot; rel=&quot;tag&quot;&gt;AltersArmut&lt;/a&gt;&lt;/span&gt; ..... &lt;br /&gt; &lt;br /&gt; &lt;a href=&quot;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&quot; title=&quot;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot;&gt;http://www.tagesschau.de/inland/btw17/bilanz-schwesig-nahles-101.html&lt;/a&gt;</content>
+ <link rel="alternate" type="text/html" href="https://social.hoergen.org/notice/222320"/>
+ <status_net notice_id="978711"></status_net>
+ </activity:object>
+ <link rel="ostatus:conversation" href="https://social.hoergen.org/conversation/98616"/>
+ <ostatus:conversation>https://social.hoergen.org/conversation/98616</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <category term="altersarmut"></category>
+ <category term="arbeitnehmerflexibilisierung"></category>
+ <category term="erwerbsminderungsrente"></category>
+ <category term="geringverdiener"></category>
+ <category term="mannxismus"></category>
+ <category term="mindestlohn"></category>
+ <source>
+ <id>https://social.hoergen.org/api/statuses/user_timeline/2.atom</id>
+ <title>hoergen</title>
+ <link rel="alternate" type="text/html" href="https://social.hoergen.org/hoergen"/>
+ <link rel="self" type="application/atom+xml" href="https://social.hoergen.org/api/statuses/user_timeline/2.atom"/>
+ <icon>https://social.stopwatchingus-heidelberg.de/avatar/54316-original-20170824072526.jpeg</icon>
+ <updated>2017-08-24T09:48:30+00:00</updated>
+ </source>
+ </activity:object>
+ <link rel="ostatus:conversation" href="https://social.hoergen.org/conversation/98616"/>
+ <ostatus:conversation>https://social.hoergen.org/conversation/98616</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <category term="altersarmut"></category>
+ <category term="arbeitnehmerflexibilisierung"></category>
+ <category term="erwerbsminderungsrente"></category>
+ <category term="geringverdiener"></category>
+ <category term="mannxismus"></category>
+ <category term="mindestlohn"></category>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978735.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978735.atom"/>
+ <statusnet:notice_info local_id="978735" source="web" repeat_of="978711"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-24:noticeId=978734:objectType=comment</id>
+ <title>New comment by atarifrosch</title>
+ <content type="html">Jo, die Anzahl der Hartz-IV-Sanktionen nennt sie genausowenig wie die Anzahl der Menschen, die von den Repressionsbehörden in Obdachlosigkeit und Suizid getrieben wurden. Das würde die Erfolgszahlen dann doch ein wenig trüben, nech?</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978734"/>
+ <status_net notice_id="978734"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-24T09:18:13+00:00</published>
+ <updated>2017-08-24T09:18:13+00:00</updated>
+ <thr:in-reply-to ref="tag:social.hoergen.org,2017-08-24:noticeId=222320:objectType=note" href="https://social.hoergen.org/notice/222320"></thr:in-reply-to>
+ <link rel="related" href="https://social.hoergen.org/notice/222320"/>
+ <link rel="ostatus:conversation" href="https://social.hoergen.org/conversation/98616"/>
+ <ostatus:conversation>https://social.hoergen.org/conversation/98616</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.hoergen.org/user/2"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978734.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978734.atom"/>
+ <statusnet:notice_info local_id="978734" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-24:noticeId=978732:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">Moin-quak.</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978732"/>
+ <status_net notice_id="978732"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-24T09:09:39+00:00</published>
+ <updated>2017-08-24T09:09:39+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-24:noticeId=978732:objectType=thread:crc32=2f92b7b6"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-24:noticeId=978732:objectType=thread:crc32=2f92b7b6</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978732.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978732.atom"/>
+ <statusnet:notice_info local_id="978732" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978594:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">n8-quak!</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978594"/>
+ <status_net notice_id="978594"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-23T21:39:54+00:00</published>
+ <updated>2017-08-23T21:39:54+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978594:objectType=thread:crc32=9bdb0ac9"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978594:objectType=thread:crc32=9bdb0ac9</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978594.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978594.atom"/>
+ <statusnet:notice_info local_id="978594" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978503:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">2017-08-16 Michal Špaček: Post a boarding pass on Facebook, get your account stolen – Post a boarding pass on Facebook, get your account stolen (gilt übrinx nicht nur für Facebook)</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978503"/>
+ <status_net notice_id="978503"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-23T15:14:29+00:00</published>
+ <updated>2017-08-23T15:14:29+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978503:objectType=thread:crc32=3de05c3a"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978503:objectType=thread:crc32=3de05c3a</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978503.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978503.atom"/>
+ <statusnet:notice_info local_id="978503" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-23:fave:18330:activity:978458:2017-08-23T15:18:19+02:00</id>
+ <title>Favorite</title>
+ <content type="html">atarifrosch favorited something by einebiene: Haha, große Überraschung. &lt;a href=&quot;http://www.sueddeutsche.de/wirtschaft/abgasaffaere-software-updates-fuer-dieselautos-helfen-kaum-1.3637636&quot; title=&quot;http://www.sueddeutsche.de/wirtschaft/abgasaffaere-software-updates-fuer-dieselautos-helfen-kaum-1.3637636&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://quitter.is/url/1122672&lt;/a&gt;&lt;br /&gt; Was ich an all diesen Artikeln schade finde, ist, daß immer nur auf den Umstieg von Auto zu anderem Auto gesprochen wird. Öffis werden nicht erwähnt, Carsharing nicht, radeln nicht, und in der Stadt wäre ne Vespa auch deutlich besser als ein SUV.</content>
+ <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb>
+ <published>2017-08-23T13:18:19+00:00</published>
+ <updated>2017-08-23T13:18:19+00:00</updated>
+ <activity:object>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:quitter.is,2017-08-23:noticeId=4032910:objectType=note</id>
+ <title>New note by einebiene</title>
+ <content type="html">Haha, große Überraschung. &lt;a href=&quot;http://www.sueddeutsche.de/wirtschaft/abgasaffaere-software-updates-fuer-dieselautos-helfen-kaum-1.3637636&quot; title=&quot;http://www.sueddeutsche.de/wirtschaft/abgasaffaere-software-updates-fuer-dieselautos-helfen-kaum-1.3637636&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://quitter.is/url/1122672&lt;/a&gt;&lt;br /&gt; Was ich an all diesen Artikeln schade finde, ist, daß immer nur auf den Umstieg von Auto zu anderem Auto gesprochen wird. Öffis werden nicht erwähnt, Carsharing nicht, radeln nicht, und in der Stadt wäre ne Vespa auch deutlich besser als ein SUV.</content>
+ <link rel="alternate" type="text/html" href="https://quitter.is/notice/4032910"/>
+ <status_net notice_id="978458"></status_net>
+ </activity:object>
+ <thr:in-reply-to ref="tag:quitter.is,2017-08-23:noticeId=4032910:objectType=note" href="https://quitter.is/notice/4032910"></thr:in-reply-to>
+ <link rel="related" href="https://quitter.is/notice/4032910"/>
+ <link rel="ostatus:conversation" href="https://quitter.is/conversation/2535246"/>
+ <ostatus:conversation>https://quitter.is/conversation/2535246</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://quitter.is/user/8380"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <statusnet:notice_info local_id="978464" source="unknown"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978402:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">moin-quak</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978402"/>
+ <status_net notice_id="978402"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-23T10:57:26+00:00</published>
+ <updated>2017-08-23T10:57:26+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978402:objectType=thread:crc32=7050c397"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-23:noticeId=978402:objectType=thread:crc32=7050c397</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978402.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978402.atom"/>
+ <statusnet:notice_info local_id="978402" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978164:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">n8-quak</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978164"/>
+ <status_net notice_id="978164"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-22T19:54:30+00:00</published>
+ <updated>2017-08-22T19:54:30+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978164:objectType=thread:crc32=b0a209c7"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978164:objectType=thread:crc32=b0a209c7</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978164.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978164.atom"/>
+ <statusnet:notice_info local_id="978164" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978072:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">2017-08-22 Bundesverfassungsgericht: Erfolgreiche Verfassungsbeschwerde gegen die Versagung vorläufiger Leistungen für Kosten der Unterkunft und Heizung – &lt;a href=&quot;https://www.bundesverfassungsgericht.de/SharedDocs/Pressemitteilungen/DE/2017/bvg17-072.html&quot; title=&quot;https://www.bundesverfassungsgericht.de/SharedDocs/Pressemitteilungen/DE/2017/bvg17-072.html&quot; class=&quot;attachment&quot; id=&quot;attachment-450768&quot; rel=&quot;nofollow external&quot;&gt;https://www.bundesverfassungsgericht.de/SharedDocs/Pressemitteilungen/DE/2017/bvg17-072.html&lt;/a&gt; !&lt;a href=&quot;http://quitter.se/group/2184/id&quot; class=&quot;h-card group&quot; title=&quot;HartzIV (hartziv)&quot;&gt;hartziv&lt;/a&gt;</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978072"/>
+ <status_net notice_id="978072"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-22T12:00:21+00:00</published>
+ <updated>2017-08-22T12:00:21+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978072:objectType=thread:crc32=28a35f44"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978072:objectType=thread:crc32=28a35f44</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href=""/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/group" href="http://quitter.se/group/2184/id"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978072.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978072.atom"/>
+ <statusnet:notice_info local_id="978072" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978042:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">moin-quak!</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978042"/>
+ <status_net notice_id="978042"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-22T07:55:27+00:00</published>
+ <updated>2017-08-22T07:55:27+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978042:objectType=thread:crc32=f070a9f7"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978042:objectType=thread:crc32=f070a9f7</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978042.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978042.atom"/>
+ <statusnet:notice_info local_id="978042" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-21:noticeId=977914:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">So, morgen geht's weiter. n8-quak!</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/977914"/>
+ <status_net notice_id="977914"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-21T22:09:53+00:00</published>
+ <updated>2017-08-21T22:09:53+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-21:noticeId=977914:objectType=thread:crc32=c0a9f7fa"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-21:noticeId=977914:objectType=thread:crc32=c0a9f7fa</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977914.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977914.atom"/>
+ <statusnet:notice_info local_id="977914" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-21:noticeId=977710:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">moin-quak.</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/977710"/>
+ <status_net notice_id="977710"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-21T08:58:26+00:00</published>
+ <updated>2017-08-21T08:58:26+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-21:noticeId=977710:objectType=thread:crc32=60cfb466"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-21:noticeId=977710:objectType=thread:crc32=60cfb466</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977710.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977710.atom"/>
+ <statusnet:notice_info local_id="977710" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-20:noticeId=977526:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">Meine Augen meinen, für heute sei es genug. Nun denn. n8-quak.</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/977526"/>
+ <status_net notice_id="977526"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-20T19:58:16+00:00</published>
+ <updated>2017-08-20T19:58:16+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-20:noticeId=977526:objectType=thread:crc32=ce79634"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-20:noticeId=977526:objectType=thread:crc32=ce79634</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977526.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977526.atom"/>
+ <statusnet:notice_info local_id="977526" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-20:noticeId=977369:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">[Blog] Im Netz aufgefischt #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.stopwatchingus-heidelberg.de/tag/330&quot; rel=&quot;tag&quot;&gt;330&lt;/a&gt;&lt;/span&gt; – &lt;a href=&quot;https://blog.atari-frosch.de/2017/08/20/im-netz-aufgefischt-330/&quot; title=&quot;https://blog.atari-frosch.de/2017/08/20/im-netz-aufgefischt-330/&quot; class=&quot;attachment&quot; id=&quot;attachment-450668&quot; rel=&quot;nofollow external&quot;&gt;https://blog.atari-frosch.de/2017/08/20/im-netz-aufgefischt-330/&lt;/a&gt; (was ich diese Woche so gelesen habe)</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/977369"/>
+ <status_net notice_id="977369"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-20T09:14:07+00:00</published>
+ <updated>2017-08-20T09:14:07+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-20:noticeId=977369:objectType=thread:crc32=2f800b86"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-20:noticeId=977369:objectType=thread:crc32=2f800b86</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <category term="330"></category>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977369.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977369.atom"/>
+ <statusnet:notice_info local_id="977369" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-19:noticeId=977268:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">Fast ständig husten müssen ist echt anstrengend … naja, n8-quak.</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/977268"/>
+ <status_net notice_id="977268"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-19T21:59:20+00:00</published>
+ <updated>2017-08-19T21:59:20+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-19:noticeId=977268:objectType=thread:crc32=deda767a"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-19:noticeId=977268:objectType=thread:crc32=deda767a</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977268.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977268.atom"/>
+ <statusnet:notice_info local_id="977268" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-19:fave:18330:activity:977146:2017-08-19T21:39:26+02:00</id>
+ <title>Favorite</title>
+ <content type="html">atarifrosch favorited something by einebienezwo: Ich mach gerade Kompetenztraining.&lt;br /&gt; Ich trainiere die Kompetenz, eine halb aufgegessene Gummibärchentüte nicht ganz aufzuessen.</content>
+ <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb>
+ <published>2017-08-19T19:39:26+00:00</published>
+ <updated>2017-08-19T19:39:26+00:00</updated>
+ <activity:object>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:gnusocial.de,2017-08-19:noticeId=11011264:objectType=note</id>
+ <title>New note by einebienezwo</title>
+ <content type="html">Ich mach gerade Kompetenztraining.&lt;br /&gt; Ich trainiere die Kompetenz, eine halb aufgegessene Gummibärchentüte nicht ganz aufzuessen.</content>
+ <link rel="alternate" type="text/html" href="https://gnusocial.de/notice/11011264"/>
+ <status_net notice_id="977146"></status_net>
+ </activity:object>
+ <thr:in-reply-to ref="tag:gnusocial.de,2017-08-19:noticeId=11011264:objectType=note" href="https://gnusocial.de/notice/11011264"></thr:in-reply-to>
+ <link rel="related" href="https://gnusocial.de/notice/11011264"/>
+ <link rel="ostatus:conversation" href="https://gnusocial.de/conversation/9363945"/>
+ <ostatus:conversation>https://gnusocial.de/conversation/9363945</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gnusocial.de/user/219865"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <statusnet:notice_info local_id="977243" source="unknown"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-19:noticeId=977242:objectType=comment</id>
+ <title>New comment by atarifrosch</title>
+ <content type="html">Wir hatten hier schon Ordnungsdienst auf'm Radweg. Fotografisch dokumentiert (nicht von mir, Bekannter hatte es gesehen). Da hatte grad 'ne Pizzeria neu eröffnet …</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/977242"/>
+ <status_net notice_id="977242"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-19T19:38:53+00:00</published>
+ <updated>2017-08-19T19:38:53+00:00</updated>
+ <thr:in-reply-to ref="tag:gnusocial.de,2017-08-19:noticeId=11010978:objectType=note" href="https://gnusocial.de/notice/11010978"></thr:in-reply-to>
+ <link rel="related" href="https://gnusocial.de/notice/11010978"/>
+ <link rel="ostatus:conversation" href="https://gnusocial.de/conversation/9363813"/>
+ <ostatus:conversation>https://gnusocial.de/conversation/9363813</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gnusocial.de/user/219865"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977242.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/977242.atom"/>
+ <statusnet:notice_info local_id="977242" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-19:fave:18330:activity:977180:2017-08-19T21:37:36+02:00</id>
+ <title>Favorite</title>
+ <content type="html">atarifrosch favorited something by jcaktiv: BTW Hallo zusammen &amp;lt;3, wo ich schon mal wieder hier bin</content>
+ <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb>
+ <published>2017-08-19T19:37:36+00:00</published>
+ <updated>2017-08-19T19:37:36+00:00</updated>
+ <activity:object>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:quitter.se,2017-08-19:noticeId=17372467:objectType=note</id>
+ <title>New note by jcaktiv</title>
+ <content type="html">BTW Hallo zusammen &amp;lt;3, wo ich schon mal wieder hier bin</content>
+ <link rel="alternate" type="text/html" href="http://quitter.se/notice/17372467"/>
+ <status_net notice_id="977180"></status_net>
+ </activity:object>
+ <thr:in-reply-to ref="tag:quitter.se,2017-08-19:noticeId=17372467:objectType=note" href="http://quitter.se/notice/17372467"></thr:in-reply-to>
+ <link rel="related" href="http://quitter.se/notice/17372467"/>
+ <link rel="ostatus:conversation" href="tag:quitter.se,2017-08-19:objectType=thread:nonce=46c1c433d88aaa9f"/>
+ <ostatus:conversation>tag:quitter.se,2017-08-19:objectType=thread:nonce=46c1c433d88aaa9f</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://quitter.se/user/149873"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <statusnet:notice_info local_id="977240" source="unknown"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-19:noticeId=976985:objectType=comment</id>
+ <title>New comment by atarifrosch</title>
+ <content type="html">Jo, oder einfach mal nachfragen, so als Realitätsabgleich.</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/976985"/>
+ <status_net notice_id="976985"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-19T10:34:50+00:00</published>
+ <updated>2017-08-19T10:34:50+00:00</updated>
+ <thr:in-reply-to ref="tag:status.pirati.ca,2017-08-19:noticeId=2310317:objectType=note" href="https://status.pirati.ca/notice/2310317"></thr:in-reply-to>
+ <link rel="related" href="https://status.pirati.ca/notice/2310317"/>
+ <link rel="ostatus:conversation" href="https://gnusocial.de/conversation/9362516"/>
+ <ostatus:conversation>https://gnusocial.de/conversation/9362516</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://status.pirati.ca/user/2092"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/976985.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/976985.atom"/>
+ <statusnet:notice_info local_id="976985" source="web"></statusnet:notice_info>
+</entry>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-19:noticeId=976983:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">Schöne Alternative zu mit Werbung überladenen kommerziellen Anbietern: &lt;a href=&quot;http://ifconfig.at/&quot; title=&quot;http://ifconfig.at/&quot; class=&quot;attachment&quot; id=&quot;attachment-450636&quot; rel=&quot;nofollow external&quot;&gt;http://ifconfig.at/&lt;/a&gt; – eigene IP, Hostname etc. abfragen, mit curl dann auch in Textform zur lokalen Weiterverarbeitung in Scripten etc. Leider (noch?) kein https.</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/976983"/>
+ <status_net notice_id="976983"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-19T10:33:04+00:00</published>
+ <updated>2017-08-19T10:33:04+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-19:noticeId=976983:objectType=thread:crc32=4a3593c0"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-19:noticeId=976983:objectType=thread:crc32=4a3593c0</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/976983.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/976983.atom"/>
+ <statusnet:notice_info local_id="976983" source="web"></statusnet:notice_info>
+</entry>
+</feed>
diff --git a/test/fixtures/httpoison_mock/atarifrosch_webfinger.xml b/test/fixtures/httpoison_mock/atarifrosch_webfinger.xml
new file mode 100644
index 000000000..24188362c
--- /dev/null
+++ b/test/fixtures/httpoison_mock/atarifrosch_webfinger.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Subject>https://social.stopwatchingus-heidelberg.de/user/18330</Subject>
+ <Alias>acct:atarifrosch@social.stopwatchingus-heidelberg.de</Alias>
+ <Alias>https://social.stopwatchingus-heidelberg.de/atarifrosch</Alias>
+ <Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="https://social.stopwatchingus-heidelberg.de/atarifrosch"/>
+ <Link rel="http://gmpg.org/xfn/11" type="text/html" href="https://social.stopwatchingus-heidelberg.de/atarifrosch"/>
+ <Link rel="describedby" type="application/rdf+xml" href="https://social.stopwatchingus-heidelberg.de/atarifrosch/foaf"/>
+ <Link rel="http://apinamespace.org/atom" type="application/atomsvc+xml" href="https://social.stopwatchingus-heidelberg.de/api/statusnet/app/service/atarifrosch.xml"/>
+ <Link rel="http://apinamespace.org/twitter" href="https://social.stopwatchingus-heidelberg.de/api/"/>
+ <Link rel="http://specs.openid.net/auth/2.0/provider" href="https://social.stopwatchingus-heidelberg.de/atarifrosch"/>
+ <Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom"/>
+ <Link rel="magic-public-key" href="data:application/magic-public-key,RSA.1ZeJGulQfTrrWooBUVcqpeJUMWfIFdCU1lprlUEHOKU6XF1an0bkoFzSXxnc_USbLfkeGo_Y2FBLeB8zQbOem3hHccbDOVAo4UhnMeAhiZIMJvE3X8fsk5KEuORpsSt9UjvygxF8CZFlhd13B4jL2ai-j1nWQPOgU-jAshgQQHk=.AQAB"/>
+ <Link rel="salmon" href="https://social.stopwatchingus-heidelberg.de/main/salmon/user/18330"/>
+ <Link rel="http://salmon-protocol.org/ns/salmon-replies" href="https://social.stopwatchingus-heidelberg.de/main/salmon/user/18330"/>
+ <Link rel="http://salmon-protocol.org/ns/salmon-mention" href="https://social.stopwatchingus-heidelberg.de/main/salmon/user/18330"/>
+ <Link rel="http://ostatus.org/schema/1.0/subscribe" template="https://social.stopwatchingus-heidelberg.de/main/ostatussub?profile={uri}"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/eal_sakamoto.xml b/test/fixtures/httpoison_mock/eal_sakamoto.xml
new file mode 100644
index 000000000..934d539c9
--- /dev/null
+++ b/test/fixtures/httpoison_mock/eal_sakamoto.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Subject>acct:eal@social.sakamoto.gq</Subject><Alias>https://social.sakamoto.gq/users/eal</Alias><Link href="https://social.sakamoto.gq/users/eal/feed.atom" rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" /><Link href="https://social.sakamoto.gq/users/eal" rel="http://webfinger.net/rel/profile-page" type="text/html" /><Link href="https://social.sakamoto.gq/users/eal/salmon" rel="salmon" /><Link href="data:application/magic-public-key,RSA.z3pF85YOhhv2Zaxv9YQ7rCe1aEhetCMVHtrK63tUVGoGdsblyKnVeJNbFcr6k3y35OpHS3HXIi6GzgihYcTuONLP4eQMHTnLUNAQZi03mjJA4iIq8v_tm8ZkL2mXsQSAbWj6Iq518mHNN7OvCoNt3Xjepl_0kgkc2gsund7m8r-Wu0Fusx6UlUyyAk3PexdDRdSSlVLeskqtP8jtdQDoL70pMyL-VD-Qb9RKFdtgJ-M4OqYP-7FVzCqXN0QIPhFf_kvHSLr-c4Y3Wm0nAKHU9CwXWXz5Xqscpv41KlgnUCOkTXb5eBSt23lNulae5srVzWBiFb6guiCpNzBGa-Sqrw==.AQAB" rel="magic-public-key" /></XRD>
\ No newline at end of file
diff --git a/test/fixtures/httpoison_mock/gs.example.org_host_meta b/test/fixtures/httpoison_mock/gs.example.org_host_meta
new file mode 100644
index 000000000..c2fcd7305
--- /dev/null
+++ b/test/fixtures/httpoison_mock/gs.example.org_host_meta
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/jrd+json" template="http://gs.example.org/.well-known/webfinger?resource={uri}"/>
+ <Link rel="lrdd" type="application/json" template="http://gs.example.org/.well-known/webfinger?resource={uri}"/>
+ <Link rel="lrdd" type="application/xrd+xml" template="http://gs.example.org/.well-known/webfinger?resource={uri}"/>
+ <Link rel="http://apinamespace.org/oauth/access_token" href="http://gs.example.org/api/oauth/access_token"/>
+ <Link rel="http://apinamespace.org/oauth/request_token" href="http://gs.example.org/api/oauth/request_token"/>
+ <Link rel="http://apinamespace.org/oauth/authorize" href="http://gs.example.org/api/oauth/authorize"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/https___pawoo.net_users_aqidaqidaqid.xml b/test/fixtures/httpoison_mock/https___pawoo.net_users_aqidaqidaqid.xml
new file mode 100644
index 000000000..2de8a44b9
--- /dev/null
+++ b/test/fixtures/httpoison_mock/https___pawoo.net_users_aqidaqidaqid.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Subject>acct:aqidaqidaqid@pawoo.net</Subject>
+ <Alias>https://pawoo.net/@aqidaqidaqid</Alias>
+ <Alias>https://pawoo.net/users/aqidaqidaqid</Alias>
+ <Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="https://pawoo.net/@aqidaqidaqid"/>
+ <Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="https://pawoo.net/users/aqidaqidaqid.atom"/>
+ <Link rel="salmon" href="https://pawoo.net/api/salmon/24733"/>
+ <Link rel="magic-public-key" href="data:application/magic-public-key,RSA.mRLlTE_m1_HAm9GKPPtfKqQuTJzdDg3k1D8_MVfGHrw14KFr3QFYieV0DmXSCBWcrNcFrnw1ItFdkd7hh-cvhrBAER2MAR_YNDlGQh5RDriBidCa-FvMAYX0f5aDyy33D392OoFxre-esc54VRvCm0JSWLUpm6iNHYc36nHKIJKKW3HbmVfAWp5N-R8kP0IyB5xBWAqBPZA8pnjeXd_jygRfAxfXU7PaXkNeY3xPBpkEujJXGuUjlmz6FcZYlPfhqtNTPsiyE-ZN1u7OdFZ5TOM7zy6Wzs5xa2xhEGv-RrdPZa2OAiYT-xWPLlQsGu5YEO_fAuz3HQx4iOriVb6ndQ==.AQAB"/>
+ <Link rel="http://ostatus.org/schema/1.0/subscribe" template="https://pawoo.net/authorize_follow?acct={uri}"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/lain_squeet.me_webfinger.xml b/test/fixtures/httpoison_mock/lain_squeet.me_webfinger.xml
new file mode 100644
index 000000000..948e4758e
--- /dev/null
+++ b/test/fixtures/httpoison_mock/lain_squeet.me_webfinger.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Subject>lain@squeet.me</Subject>
+ <Alias>https://squeet.me/profile/lain</Alias>
+ <Alias>https://squeet.me/profile/lain</Alias>
+
+ <Link rel="http://purl.org/macgirvin/dfrn/1.0"
+ href="https://squeet.me/profile/lain" />
+ <Link rel="http://schemas.google.com/g/2010#updates-from"
+ type="application/atom+xml"
+ href="https://squeet.me/dfrn_poll/lain" />
+ <Link rel="http://webfinger.net/rel/profile-page"
+ type="text/html"
+ href="https://squeet.me/profile/lain" />
+ <Link rel="http://microformats.org/profile/hcard"
+ type="text/html"
+ href="https://squeet.me/hcard/lain" />
+ <Link rel="http://portablecontacts.net/spec/1.0"
+ href="https://squeet.me/poco/lain" />
+ <Link rel="http://webfinger.net/rel/avatar"
+ type="image/jpeg"
+ href="https://squeet.me/photo/profile/301.jpg" />
+ <Link rel="http://joindiaspora.com/seed_location" type="text/html" href="https://squeet.me/" />
+ <Link rel="http://joindiaspora.com/guid" type="text/html" href="962c3e1016599bd8cede8a9274362922" />
+ <Link rel="diaspora-public-key" type="RSA" href="LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUNDZ0tDQWdFQTNkM0JPUkdITHJSWXZYNUFGcEhzeTlpQy9wSlVBSHl4dlhYQW04S3RvRkpqTFZZc2N0bS8KclJwTE81OE5rTUZlTTZOQWJMWmROOFArdEdLNFBORWhsSWNqek9DdS82UmxjVGZwWU9yaDdaeWtWNmk1UlVHRApKQ3JJcjJ5OUVURXBFL09zZ25QNVEwVmpJWWwxdVJLNytPeGZHOGVUTjhDVnpnY2pjM205MnM0MjBXS2dKTHA1CmFaVkRESS9OcHYwektlVi9Pb21Fb2N6U1ZuckEzZGZKSkltQ3IxdWpvUEoyOVJzb1dpeCtLMjJWZU5BdVlOYmUKeWdXY3F3cTlZeWRNaDNqUEVNRVZXUzMvRjZuTE9VS084MDAzY2p1V1NxNXhvZkptVnJkMVlCVFFWR0wzOUNXMAorQUFVcEJhMXc0YWcvc1Nya0xsMFk1QUs0akJKcHVpbHFZcXFtRXlVS2NTWElHVlIyNG5UWWdlWExCRDFtcS80CmVnaTc1eUtWbysrRVdYUTlyb0oxblUxVHYvbkRDY0lYSWE4Zi9uNEpMTk8wTG1DR01aWjVjS3dnMFBmVUZkdEoKK3UwL2UrczFyWmk5d0JZb1B5RGhGM1ZPS0Z5REs1b0xUVEJ6ZERlTklYUjdDc004VElSZnkyaU1rSTh4NTRCQgp3TkFrZGV0b3owZXFrZmFyejd2TUdWajB0SWRZZWRmTFpFYk1jSUVWTk1kWXhqUWJnSGZ3aGUxZ2xZS2RLdmNECjhCanpZU1VDR2Q2ZitSR2ZrYXBvaFBqanBSbW1QaHhlZHNlTEVpZkZMQ2JvWTlUSUIrR1V2NXJPTG1iblVsL3IKdE42dzRsRzlqQ2F1a25UYU5LSmVYVlRmRGRBSE9FbFZLdTN2L05taTA2dnlkMzhWS1JlSFc3OENBd0VBQVE9PQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCg==" />
+
+ <Link rel="salmon"
+ href="https://squeet.me/salmon/lain" />
+ <Link rel="http://salmon-protocol.org/ns/salmon-replies"
+ href="https://squeet.me/salmon/lain" />
+ <Link rel="http://salmon-protocol.org/ns/salmon-mention"
+ href="https://squeet.me/salmon/lain/mention" />
+ <Link rel="http://ostatus.org/schema/1.0/subscribe"
+ template="https://squeet.me/follow?url={uri}" />
+ <Link rel="magic-public-key"
+ href="data:application/magic-public-key,RSA.AMwa8FUs2fWEjX0xN7yRQgegQffhBpuKNC6fa5VNSVorFjGZhRrlPMn7TQOeihlc9lBz2OsHlIedbYn2uJ7yCs0.AQAB" />
+
+ <Property xmlns:mk="http://salmon-protocol.org/ns/magic-key"
+ type="http://salmon-protocol.org/ns/magic-key"
+ mk:key_id="1">RSA.AN3dwTkRhy60WL1-QBaR7MvYgv6SVAB8sb11wJvCraBSYy1WLHLZv60aSzufDZDBXjOjQGy2XTfD_rRiuDzRIZSHI8zgrv-kZXE36WDq4e2cpFeouUVBgyQqyK9svRExKRPzrIJz-UNFYyGJdbkSu_jsXxvHkzfAlc4HI3N5vdrONtFioCS6eWmVQwyPzab9MynlfzqJhKHM0lZ6wN3XySSJgq9bo6DydvUbKFosfittlXjQLmDW3soFnKsKvWMnTId4zxDBFVkt_xepyzlCjvNNN3I7lkqucaHyZla3dWAU0FRi9_QltPgAFKQWtcOGoP7Eq5C5dGOQCuIwSabopamKqphMlCnElyBlUduJ02IHlywQ9Zqv-HoIu-cilaPvhFl0Pa6CdZ1NU7_5wwnCFyGvH_5-CSzTtC5ghjGWeXCsIND31BXbSfrtP3vrNa2YvcAWKD8g4Rd1TihcgyuaC00wc3Q3jSF0ewrDPEyEX8tojJCPMeeAQcDQJHXraM9HqpH2q8-7zBlY9LSHWHnXy2RGzHCBFTTHWMY0G4B38IXtYJWCnSr3A_AY82ElAhnen_kRn5GqaIT446UZpj4cXnbHixInxSwm6GPUyAfhlL-azi5m51Jf67TesOJRvYwmrpJ02jSiXl1U3w3QBzhJVSrt7_zZotOr8nd_FSkXh1u_.AQAB</Property>
+
+</XRD>
diff --git a/test/fixtures/httpoison_mock/macgirvin.com_host_meta b/test/fixtures/httpoison_mock/macgirvin.com_host_meta
new file mode 100644
index 000000000..cd30b602f
--- /dev/null
+++ b/test/fixtures/httpoison_mock/macgirvin.com_host_meta
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'
+ xmlns:hm='http://host-meta.net/xrd/1.0'>
+
+ <hm:Host>macgirvin.com</hm:Host>
+
+ <Link rel='lrdd' type="application/xrd+xml" template='https://macgirvin.com/xrd/?uri={uri}' />
+ <Link rel="http://oexchange.org/spec/0.8/rel/resident-target" type="application/xrd+xml"
+ href="https://macgirvin.com/oexchange/xrd" />
+
+</XRD>
diff --git a/test/fixtures/httpoison_mock/mamot.fr_host_meta b/test/fixtures/httpoison_mock/mamot.fr_host_meta
new file mode 100644
index 000000000..ed7a95094
--- /dev/null
+++ b/test/fixtures/httpoison_mock/mamot.fr_host_meta
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/xrd+xml" template="https://mamot.fr/.well-known/webfinger?resource={uri}"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/mastodon.social_host_meta b/test/fixtures/httpoison_mock/mastodon.social_host_meta
new file mode 100644
index 000000000..78e46e260
--- /dev/null
+++ b/test/fixtures/httpoison_mock/mastodon.social_host_meta
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/xrd+xml" template="https://mastodon.social/.well-known/webfinger?resource={uri}"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/mastodon.xyz_host_meta b/test/fixtures/httpoison_mock/mastodon.xyz_host_meta
new file mode 100644
index 000000000..8604316fb
--- /dev/null
+++ b/test/fixtures/httpoison_mock/mastodon.xyz_host_meta
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/xrd+xml" template="https://mastodon.xyz/.well-known/webfinger?resource={uri}"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/pawoo.net_host_meta b/test/fixtures/httpoison_mock/pawoo.net_host_meta
new file mode 100644
index 000000000..dbbe7be5f
--- /dev/null
+++ b/test/fixtures/httpoison_mock/pawoo.net_host_meta
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/xrd+xml" template="https://pawoo.net/.well-known/webfinger?resource={uri}"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/pleroma.soykaf.com_host_meta b/test/fixtures/httpoison_mock/pleroma.soykaf.com_host_meta
new file mode 100644
index 000000000..fb5c15a4f
--- /dev/null
+++ b/test/fixtures/httpoison_mock/pleroma.soykaf.com_host_meta
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" template="https://pleroma.soykaf.com/.well-known/webfinger?resource={uri}" type="application/xrd+xml" /></XRD>
\ No newline at end of file
diff --git a/test/fixtures/httpoison_mock/shitposter.club_host_meta b/test/fixtures/httpoison_mock/shitposter.club_host_meta
new file mode 100644
index 000000000..9d012e1df
--- /dev/null
+++ b/test/fixtures/httpoison_mock/shitposter.club_host_meta
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/jrd+json" template="https://shitposter.club/.well-known/webfinger?resource={uri}"/>
+ <Link rel="lrdd" type="application/json" template="https://shitposter.club/.well-known/webfinger?resource={uri}"/>
+ <Link rel="lrdd" type="application/xrd+xml" template="https://shitposter.club/.well-known/webfinger?resource={uri}"/>
+ <Link rel="http://apinamespace.org/oauth/access_token" href="https://shitposter.club/api/oauth/access_token"/>
+ <Link rel="http://apinamespace.org/oauth/request_token" href="https://shitposter.club/api/oauth/request_token"/>
+ <Link rel="http://apinamespace.org/oauth/authorize" href="https://shitposter.club/api/oauth/authorize"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/social.heldscal.la_host_meta b/test/fixtures/httpoison_mock/social.heldscal.la_host_meta
new file mode 100644
index 000000000..540e6257e
--- /dev/null
+++ b/test/fixtures/httpoison_mock/social.heldscal.la_host_meta
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/jrd+json" template="https://social.heldscal.la/.well-known/webfinger?resource={uri}"/>
+ <Link rel="lrdd" type="application/json" template="https://social.heldscal.la/.well-known/webfinger?resource={uri}"/>
+ <Link rel="lrdd" type="application/xrd+xml" template="https://social.heldscal.la/.well-known/webfinger?resource={uri}"/>
+ <Link rel="http://apinamespace.org/oauth/access_token" href="https://social.heldscal.la/api/oauth/access_token"/>
+ <Link rel="http://apinamespace.org/oauth/request_token" href="https://social.heldscal.la/api/oauth/request_token"/>
+ <Link rel="http://apinamespace.org/oauth/authorize" href="https://social.heldscal.la/api/oauth/authorize"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/social.sakamoto.gq_host_meta b/test/fixtures/httpoison_mock/social.sakamoto.gq_host_meta
new file mode 100644
index 000000000..f193dce2b
--- /dev/null
+++ b/test/fixtures/httpoison_mock/social.sakamoto.gq_host_meta
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" template="https://social.sakamoto.gq/.well-known/webfinger?resource={uri}" type="application/xrd+xml" /></XRD>
\ No newline at end of file
diff --git a/test/fixtures/httpoison_mock/social.stopwatchingus-heidelberg.de_host_meta b/test/fixtures/httpoison_mock/social.stopwatchingus-heidelberg.de_host_meta
new file mode 100644
index 000000000..aafc9f60d
--- /dev/null
+++ b/test/fixtures/httpoison_mock/social.stopwatchingus-heidelberg.de_host_meta
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/jrd+json" template="https://social.stopwatchingus-heidelberg.de/.well-known/webfinger?resource={uri}"/>
+ <Link rel="lrdd" type="application/json" template="https://social.stopwatchingus-heidelberg.de/.well-known/webfinger?resource={uri}"/>
+ <Link rel="lrdd" type="application/xrd+xml" template="https://social.stopwatchingus-heidelberg.de/.well-known/webfinger?resource={uri}"/>
+ <Link rel="http://apinamespace.org/oauth/access_token" href="https://social.stopwatchingus-heidelberg.de/api/oauth/access_token"/>
+ <Link rel="http://apinamespace.org/oauth/request_token" href="https://social.stopwatchingus-heidelberg.de/api/oauth/request_token"/>
+ <Link rel="http://apinamespace.org/oauth/authorize" href="https://social.stopwatchingus-heidelberg.de/api/oauth/authorize"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/social.wxcafe.net_host_meta b/test/fixtures/httpoison_mock/social.wxcafe.net_host_meta
new file mode 100644
index 000000000..5ffc40a90
--- /dev/null
+++ b/test/fixtures/httpoison_mock/social.wxcafe.net_host_meta
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" type="application/xrd+xml" template="https://social.wxcafe.net/.well-known/webfinger?resource={uri}"/>
+</XRD>
diff --git a/test/fixtures/httpoison_mock/squeet.me_host_meta b/test/fixtures/httpoison_mock/squeet.me_host_meta
new file mode 100644
index 000000000..4a94ae574
--- /dev/null
+++ b/test/fixtures/httpoison_mock/squeet.me_host_meta
@@ -0,0 +1,16 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'
+ xmlns:hm='http://host-meta.net/xrd/1.0'>
+
+ <hm:Host>squeet.me</hm:Host>
+
+ <Link rel='lrdd' type='application/xrd+xml' template='https://squeet.me/xrd/?uri={uri}' />
+ <Link rel='acct-mgmt' href='https://squeet.me/amcd' />
+ <Link rel='http://services.mozilla.com/amcd/0.1' href='https://squeet.me/amcd' />
+ <Link rel="http://oexchange.org/spec/0.8/rel/resident-target" type="application/xrd+xml"
+ href="https://squeet.me/oexchange/xrd" />
+
+ <Property xmlns:mk="http://salmon-protocol.org/ns/magic-key"
+ type="http://salmon-protocol.org/ns/magic-key"
+ mk:key_id="1">RSA.AMZTNgTQx_YZzt1urzlHyefrXFAml_q8fpCsnUHeIbdtQLeA-HdTK2epwELu653-aK_WGUYSKYLyb1walkqNM5gC5FGVFa7EvVoR-uSNKrduFzUz2SdRXTw3e3NQtd9Rs5Mpgm1wYnt1NiWk-7dKIpoVilHgOOYDX15NU9Zfu7-J.AQAB</Property>
+</XRD>
diff --git a/test/fixtures/nil_mention_entry.xml b/test/fixtures/nil_mention_entry.xml
new file mode 100644
index 000000000..e13024cb3
--- /dev/null
+++ b/test/fixtures/nil_mention_entry.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:georss="http://www.georss.org/georss" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:media="http://purl.org/syndication/atommedia" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:statusnet="http://status.net/schema/api/1/">
+ <generator uri="https://gnu.io/social" version="1.2.0-alpha2">GNU social</generator>
+ <id>https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom</id>
+ <title>atarifrosch timeline</title>
+ <subtitle>Updates from atarifrosch on social.stopwatchingus-heidelberg.de!</subtitle>
+ <logo>https://social.stopwatchingus-heidelberg.de/avatar/18330-96-20150628163706.png</logo>
+ <updated>2017-08-24T11:36:49+02:00</updated>
+<author>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
+ <uri>https://social.stopwatchingus-heidelberg.de/user/18330</uri>
+ <name>atarifrosch</name>
+ <summary>Nerd, Pirat, Debian user, CAcert assurer, Geocacher, Freifunker. Autismus/Depression, agender. GnuPG Key-ID: 0xBCF81ADE</summary>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/atarifrosch"/>
+ <link rel="avatar" type="image/png" media:width="480" media:height="480" href="https://social.stopwatchingus-heidelberg.de/avatar/18330-480-20150628163705.png"/>
+ <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://social.stopwatchingus-heidelberg.de/avatar/18330-96-20150628163706.png"/>
+ <link rel="avatar" type="image/png" media:width="48" media:height="48" href="https://social.stopwatchingus-heidelberg.de/avatar/18330-48-20150628163713.png"/>
+ <link rel="avatar" type="image/png" media:width="24" media:height="24" href="https://social.stopwatchingus-heidelberg.de/avatar/18330-24-20150628163714.png"/>
+ <poco:preferredUsername>atarifrosch</poco:preferredUsername>
+ <poco:displayName>Atari-Frosch</poco:displayName>
+ <poco:note>Nerd, Pirat, Debian user, CAcert assurer, Geocacher, Freifunker. Autismus/Depression, agender. GnuPG Key-ID: 0xBCF81ADE</poco:note>
+ <poco:address>
+ <poco:formatted>Düsseldorf, NRW, Germany</poco:formatted>
+ </poco:address>
+ <poco:urls>
+ <poco:type>homepage</poco:type>
+ <poco:value>https://www.atari-frosch.de/</poco:value>
+ <poco:primary>true</poco:primary>
+ </poco:urls>
+ <followers url="https://social.stopwatchingus-heidelberg.de/atarifrosch/subscribers"></followers>
+ <statusnet:profile_info local_id="18330"></statusnet:profile_info>
+</author>
+<entry>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <id>tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978072:objectType=note</id>
+ <title>New note by atarifrosch</title>
+ <content type="html">2017-08-22 Bundesverfassungsgericht: Erfolgreiche Verfassungsbeschwerde gegen die Versagung vorläufiger Leistungen für Kosten der Unterkunft und Heizung – &lt;a href=&quot;https://www.bundesverfassungsgericht.de/SharedDocs/Pressemitteilungen/DE/2017/bvg17-072.html&quot; title=&quot;https://www.bundesverfassungsgericht.de/SharedDocs/Pressemitteilungen/DE/2017/bvg17-072.html&quot; class=&quot;attachment&quot; id=&quot;attachment-450768&quot; rel=&quot;nofollow external&quot;&gt;https://www.bundesverfassungsgericht.de/SharedDocs/Pressemitteilungen/DE/2017/bvg17-072.html&lt;/a&gt; !&lt;a href=&quot;http://quitter.se/group/2184/id&quot; class=&quot;h-card group&quot; title=&quot;HartzIV (hartziv)&quot;&gt;hartziv&lt;/a&gt;</content>
+ <link rel="alternate" type="text/html" href="https://social.stopwatchingus-heidelberg.de/notice/978072"/>
+ <status_net notice_id="978072"></status_net>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
+ <published>2017-08-22T12:00:21+00:00</published>
+ <updated>2017-08-22T12:00:21+00:00</updated>
+ <link rel="ostatus:conversation" href="tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978072:objectType=thread:crc32=28a35f44"/>
+ <ostatus:conversation>tag:social.stopwatchingus-heidelberg.de,2017-08-22:noticeId=978072:objectType=thread:crc32=28a35f44</ostatus:conversation>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href=""/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/group" href="http://quitter.se/group/2184/id"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
+ <link rel="self" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978072.atom"/>
+ <link rel="edit" type="application/atom+xml" href="https://social.stopwatchingus-heidelberg.de/api/statuses/show/978072.atom"/>
+ <statusnet:notice_info local_id="978072" source="web"></statusnet:notice_info>
+</entry>
+</feed>
diff --git a/test/support/httpoison_mock.ex b/test/support/httpoison_mock.ex
index 08b566fcd..091fb9ded 100644
--- a/test/support/httpoison_mock.ex
+++ b/test/support/httpoison_mock.ex
@@ -1,181 +1,363 @@
defmodule HTTPoisonMock do
alias HTTPoison.Response
def get(url, body \\ [], headers \\ [])
def get("https://social.heldscal.la/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "nonexistant@social.heldscal.la"]]) do
{:ok, %Response{
status_code: 500,
body: File.read!("test/fixtures/httpoison_mock/nonexistant@social.heldscal.la.xml")
}}
end
+ def get("https://social.heldscal.la/.well-known/webfinger?resource=shp@social.heldscal.la", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/shp@social.heldscal.la.xml")
+ }}
+ end
+
def get("https://social.heldscal.la/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "shp@social.heldscal.la"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/shp@social.heldscal.la.xml")
}}
end
def get("https://social.heldscal.la/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "https://social.heldscal.la/user/23211"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_23211.xml")
}}
end
-
+
+ def get("https://social.heldscal.la/.well-known/webfinger?resource=https://social.heldscal.la/user/23211", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_23211.xml")
+ }}
+ end
+
def get("https://social.heldscal.la/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "https://social.heldscal.la/user/29191"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_29191.xml")
}}
end
+ def get("https://social.heldscal.la/.well-known/webfinger?resource=https://social.heldscal.la/user/29191", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_29191.xml")
+ }}
+ end
+
def get("https://mastodon.social/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "https://mastodon.social/users/lambadalambda"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___mastodon.social_users_lambadalambda.xml")
}}
end
+ def get("https://mastodon.social/.well-known/webfinger?resource=https://mastodon.social/users/lambadalambda", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/https___mastodon.social_users_lambadalambda.xml")
+ }}
+ end
+
def get("https://shitposter.club/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "https://shitposter.club/user/1"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___shitposter.club_user_1.xml")
}}
end
+ def get("https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/1", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/https___shitposter.club_user_1.xml")
+ }}
+ end
+
def get("http://gs.example.org/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "http://gs.example.org:4040/index.php/user/1"], follow_redirect: true]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/http___gs.example.org_4040_index.php_user_1.xml")
}}
end
+ def get("http://gs.example.org/.well-known/webfinger?resource=http://gs.example.org:4040/index.php/user/1", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/http___gs.example.org_4040_index.php_user_1.xml")
+ }}
+ end
+
+ def get("https://social.stopwatchingus-heidelberg.de/.well-known/webfinger?resource=https://social.stopwatchingus-heidelberg.de/user/18330", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/atarifrosch_webfinger.xml")
+ }}
+ end
+
def get("https://pleroma.soykaf.com/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "https://pleroma.soykaf.com/users/lain"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pleroma.soykaf.com_users_lain.xml")
}}
end
+ def get("https://pleroma.soykaf.com/.well-known/webfinger?resource=https://pleroma.soykaf.com/users/lain", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/https___pleroma.soykaf.com_users_lain.xml")
+ }}
+ end
+
def get("https://social.heldscal.la/api/statuses/user_timeline/29191.atom", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_api_statuses_user_timeline_29191.atom.xml")
}}
end
def get("https://social.heldscal.la/api/statuses/user_timeline/23211.atom", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_api_statuses_user_timeline_23211.atom.xml")
}}
end
def get("https://mastodon.social/users/lambadalambda.atom", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___mastodon.social_users_lambadalambda.atom")
}}
end
+ def get("https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom", _body, _headers) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/atarifrosch_feed.xml")
+ }}
+ end
+
def get("https://pleroma.soykaf.com/users/lain/feed.atom", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pleroma.soykaf.com_users_lain_feed.atom.xml")
}}
end
def get("https://social.sakamoto.gq/users/eal/feed.atom", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/sakamoto_eal_feed.atom")
}}
end
def get("http://gs.example.org/index.php/api/statuses/user_timeline/1.atom", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/http__gs.example.org_index.php_api_statuses_user_timeline_1.atom.xml")
}}
end
def get("https://shitposter.club/notice/2827873", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___shitposter.club_notice_2827873.html")
}}
end
def get("https://shitposter.club/api/statuses/show/2827873.atom", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___shitposter.club_api_statuses_show_2827873.atom.xml")
}}
end
def get("https://shitposter.club/api/statuses/user_timeline/1.atom", _body, _headers) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___shitposter.club_api_statuses_user_timeline_1.atom.xml")
}}
end
def post("https://social.heldscal.la/main/push/hub", {:form, data}, ["Content-type": "application/x-www-form-urlencoded"]) do
{:ok, %Response{
status_code: 202
}}
end
def get("https://pawoo.net/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "https://pawoo.net/users/pekorino"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pawoo.net_users_pekorino.xml")
}}
end
+ def get("https://pawoo.net/.well-known/webfinger?resource=https://pawoo.net/users/pekorino", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/https___pawoo.net_users_pekorino.xml")
+ }}
+ end
+
def get("https://pawoo.net/users/pekorino.atom", _, _) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pawoo.net_users_pekorino.atom")
}}
end
def get("https://mamot.fr/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "https://mamot.fr/users/Skruyb"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/skruyb@mamot.fr.atom")
}}
end
+ def get("https://mamot.fr/.well-known/webfinger?resource=https://mamot.fr/users/Skruyb", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/skruyb@mamot.fr.atom")
+ }}
+ end
+
def get("https://social.sakamoto.gq/.well-known/webfinger", [Accept: "application/xrd+xml"], [params: [resource: "https://social.sakamoto.gq/users/eal"]]) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/eal_sakamoto.xml")
}}
end
+ def get("https://social.sakamoto.gq/.well-known/webfinger?resource=https://social.sakamoto.gq/users/eal", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/eal_sakamoto.xml")
+ }}
+ end
+
+ def get("https://squeet.me/xrd/?uri=lain@squeet.me", [Accept: "application/xrd+xml"], []) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/lain_squeet.me_webfinger.xml")
+ }}
+ end
+
def get("https://mamot.fr/users/Skruyb.atom", _, _) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___mamot.fr_users_Skruyb.atom")
}}
end
def get("https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056", [Accept: "application/atom+xml"], _) do
{:ok, %Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/sakamoto.atom")
}}
end
+ def get("http://social.heldscal.la/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/social.heldscal.la_host_meta")
+ }}
+ end
+
+ def get("http://macgirvin.com/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/macgirvin.com_host_meta")
+ }}
+ end
+
+ def get("http://mastodon.social/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/mastodon.social_host_meta")
+ }}
+ end
+
+ def get("http://shitposter.club/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/shitposter.club_host_meta")
+ }}
+ end
+
+ def get("http://pleroma.soykaf.com/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/pleroma.soykaf.com_host_meta")
+ }}
+ end
+
+ def get("http://social.sakamoto.gq/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/social.sakamoto.gq_host_meta")
+ }}
+ end
+
+ def get("http://gs.example.org/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/gs.example.org_host_meta")
+ }}
+ end
+
+ def get("http://pawoo.net/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/pawoo.net_host_meta")
+ }}
+ end
+
+ def get("http://mamot.fr/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/mamot.fr_host_meta")
+ }}
+ end
+
+ def get("http://mastodon.xyz/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/mastodon.xyz_host_meta")
+ }}
+ end
+
+ def get("http://social.wxcafe.net/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/social.wxcafe.net_host_meta")
+ }}
+ end
+
+ def get("http://squeet.me/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/squeet.me_host_meta")
+ }}
+ end
+
+ def get("http://social.stopwatchingus-heidelberg.de/.well-known/host-meta", [], [follow_redirect: true]) do
+ {:ok, %Response{
+ status_code: 200,
+ body: File.read!("test/fixtures/httpoison_mock/social.stopwatchingus-heidelberg.de_host_meta")
+ }}
+ end
+
def get(url, body, headers) do
{:error, "Not implemented the mock response for get #{inspect(url)}, #{inspect(body)}, #{inspect(headers)}"}
end
def post(url, body, headers) do
{:error, "Not implemented the mock response for post #{inspect(url)}"}
end
end
diff --git a/test/web/ostatus/ostatus_test.exs b/test/web/ostatus/ostatus_test.exs
index 44d687d8e..8dd3c3b54 100644
--- a/test/web/ostatus/ostatus_test.exs
+++ b/test/web/ostatus/ostatus_test.exs
@@ -1,349 +1,356 @@
defmodule Pleroma.Web.OStatusTest do
use Pleroma.DataCase
alias Pleroma.Web.OStatus
alias Pleroma.Web.XML
alias Pleroma.{Object, Repo, User, Activity}
import Pleroma.Factory
test "don't insert create notes twice" do
incoming = File.read!("test/fixtures/incoming_note_activity.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert {:ok, [activity]} == OStatus.handle_incoming(incoming)
end
test "handle incoming note - GS, Salmon" do
incoming = File.read!("test/fixtures/incoming_note_activity.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
user = User.get_by_ap_id(activity.data["actor"])
assert user.info["note_count"] == 1
assert activity.data["type"] == "Create"
assert activity.data["object"]["type"] == "Note"
assert activity.data["object"]["id"] == "tag:gs.example.org:4040,2017-04-23:noticeId=29:objectType=note"
assert activity.data["published"] == "2017-04-23T14:51:03+00:00"
assert activity.data["object"]["published"] == "2017-04-23T14:51:03+00:00"
assert activity.data["context"] == "tag:gs.example.org:4040,2017-04-23:objectType=thread:nonce=f09e22f58abd5c7b"
assert "http://pleroma.example.org:4000/users/lain3" in activity.data["to"]
assert activity.local == false
end
test "handle incoming notes - GS, subscription" do
incoming = File.read!("test/fixtures/ostatus_incoming_post.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Create"
assert activity.data["object"]["type"] == "Note"
assert activity.data["object"]["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"]["content"] == "Will it blend?"
user = User.get_cached_by_ap_id(activity.data["actor"])
assert User.ap_followers(user) in activity.data["to"]
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
end
test "handle incoming notes with attachments - GS, subscription" do
incoming = File.read!("test/fixtures/incoming_websub_gnusocial_attachments.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Create"
assert activity.data["object"]["type"] == "Note"
assert activity.data["object"]["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"]["attachment"] |> length == 2
assert activity.data["object"]["external_url"] == "https://social.heldscal.la/notice/2020923"
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
end
test "handle incoming notes with tags" do
incoming = File.read!("test/fixtures/ostatus_incoming_post_tag.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert activity.data["object"]["tag"] == ["nsfw"]
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
end
test "handle incoming notes - Mastodon, salmon, reply" do
# It uses the context of the replied to object
Repo.insert!(%Object{
data: %{
"id" => "https://pleroma.soykaf.com/objects/c237d966-ac75-4fe3-a87a-d89d71a3a7a4",
"context" => "2hu"
}})
incoming = File.read!("test/fixtures/incoming_reply_mastodon.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Create"
assert activity.data["object"]["type"] == "Note"
assert activity.data["object"]["actor"] == "https://mastodon.social/users/lambadalambda"
assert activity.data["context"] == "2hu"
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
end
test "handle incoming notes - Mastodon, with CW" do
incoming = File.read!("test/fixtures/mastodon-note-cw.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Create"
assert activity.data["object"]["type"] == "Note"
assert activity.data["object"]["actor"] == "https://mastodon.social/users/lambadalambda"
assert String.contains?(activity.data["object"]["content"], "technologic")
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
end
test "handle incoming retweets - Mastodon, with CW" do
incoming = File.read!("test/fixtures/cw_retweet.xml")
{:ok, [[activity, retweeted_activity]]} = OStatus.handle_incoming(incoming)
assert String.contains?(retweeted_activity.data["object"]["content"], "Hey.")
end
test "handle incoming notes - GS, subscription, reply" do
incoming = File.read!("test/fixtures/ostatus_incoming_reply.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Create"
assert activity.data["object"]["type"] == "Note"
assert activity.data["object"]["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"]["content"] == "@<a href=\"https://gs.archae.me/user/4687\" class=\"h-card u-url p-nickname mention\" title=\"shpbot\">shpbot</a> why not indeed."
assert activity.data["object"]["inReplyTo"] == "tag:gs.archae.me,2017-04-30:noticeId=778260:objectType=note"
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
end
test "handle incoming retweets - GS, subscription" do
incoming = File.read!("test/fixtures/share-gs.xml")
{:ok, [[activity, retweeted_activity]]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Announce"
assert activity.data["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"] == retweeted_activity.data["object"]["id"]
assert "https://pleroma.soykaf.com/users/lain" in activity.data["to"]
refute activity.local
retweeted_activity = Repo.get(Activity, retweeted_activity.id)
assert retweeted_activity.data["type"] == "Create"
assert retweeted_activity.data["actor"] == "https://pleroma.soykaf.com/users/lain"
refute retweeted_activity.local
assert retweeted_activity.data["object"]["announcement_count"] == 1
assert String.contains?(retweeted_activity.data["object"]["content"], "mastodon")
refute String.contains?(retweeted_activity.data["object"]["content"], "Test account")
end
test "handle incoming retweets - GS, subscription - local message" do
incoming = File.read!("test/fixtures/share-gs-local.xml")
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
incoming = incoming
|> String.replace("LOCAL_ID", note_activity.data["object"]["id"])
|> String.replace("LOCAL_USER", user.ap_id)
{:ok, [[activity, retweeted_activity]]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Announce"
assert activity.data["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"] == retweeted_activity.data["object"]["id"]
assert user.ap_id in activity.data["to"]
refute activity.local
retweeted_activity = Repo.get(Activity, retweeted_activity.id)
assert note_activity.id == retweeted_activity.id
assert retweeted_activity.data["type"] == "Create"
assert retweeted_activity.data["actor"] == user.ap_id
assert retweeted_activity.local
assert retweeted_activity.data["object"]["announcement_count"] == 1
end
test "handle incoming retweets - Mastodon, salmon" do
incoming = File.read!("test/fixtures/share.xml")
{:ok, [[activity, retweeted_activity]]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Announce"
assert activity.data["actor"] == "https://mastodon.social/users/lambadalambda"
assert activity.data["object"] == retweeted_activity.data["object"]["id"]
assert activity.data["id"] == "tag:mastodon.social,2017-05-03:objectId=4934452:objectType=Status"
refute activity.local
assert retweeted_activity.data["type"] == "Create"
assert retweeted_activity.data["actor"] == "https://pleroma.soykaf.com/users/lain"
refute retweeted_activity.local
refute String.contains?(retweeted_activity.data["object"]["content"], "Test account")
end
test "handle incoming favorites - GS, websub" do
incoming = File.read!("test/fixtures/favorite.xml")
{:ok, [[activity, favorited_activity]]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Like"
assert activity.data["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"] == favorited_activity.data["object"]["id"]
assert activity.data["id"] == "tag:social.heldscal.la,2017-05-05:fave:23211:comment:2061643:2017-05-05T09:12:50+00:00"
refute activity.local
assert favorited_activity.data["type"] == "Create"
assert favorited_activity.data["actor"] == "https://shitposter.club/user/1"
assert favorited_activity.data["object"]["id"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
refute favorited_activity.local
end
test "handle incoming favorites with locally available object - GS, websub" do
note_activity = insert(:note_activity)
incoming = File.read!("test/fixtures/favorite_with_local_note.xml")
|> String.replace("localid", note_activity.data["object"]["id"])
{:ok, [[activity, favorited_activity]]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Like"
assert activity.data["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"] == favorited_activity.data["object"]["id"]
refute activity.local
assert note_activity.id == favorited_activity.id
assert favorited_activity.local
end
test "handle incoming replies" do
incoming = File.read!("test/fixtures/incoming_note_activity_answer.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Create"
assert activity.data["object"]["type"] == "Note"
assert activity.data["object"]["inReplyTo"] == "http://pleroma.example.org:4000/objects/55bce8fc-b423-46b1-af71-3759ab4670bc"
assert "http://pleroma.example.org:4000/users/lain5" in activity.data["to"]
assert activity.data["object"]["id"] == "tag:gs.example.org:4040,2017-04-25:noticeId=55:objectType=note"
assert "https://www.w3.org/ns/activitystreams#Public" in activity.data["to"]
end
test "handle incoming follows" do
incoming = File.read!("test/fixtures/follow.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Follow"
assert activity.data["id"] == "tag:social.heldscal.la,2017-05-07:subscription:23211:person:44803:2017-05-07T09:54:48+00:00"
assert activity.data["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"] == "https://pawoo.net/users/pekorino"
refute activity.local
follower = User.get_by_ap_id(activity.data["actor"])
followed = User.get_by_ap_id(activity.data["object"])
assert User.following?(follower, followed)
end
describe "new remote user creation" do
test "returns local users" do
local_user = insert(:user)
{:ok, user} = OStatus.find_or_make_user(local_user.ap_id)
assert user == local_user
end
test "tries to use the information in poco fields" do
uri = "https://social.heldscal.la/user/23211"
{:ok, user} = OStatus.find_or_make_user(uri)
user = Repo.get(Pleroma.User, user.id)
assert user.name == "Constance Variable"
assert user.nickname == "lambadalambda@social.heldscal.la"
assert user.local == false
assert user.info["uri"] == uri
assert user.ap_id == uri
assert user.bio == "Call me Deacon Blues."
assert user.avatar["type"] == "Image"
{:ok, user_again} = OStatus.find_or_make_user(uri)
assert user == user_again
end
test "find_make_or_update_user takes an author element and returns an updated user" do
uri = "https://social.heldscal.la/user/23211"
{:ok, user} = OStatus.find_or_make_user(uri)
old_name = user.name
old_bio = user.bio
change = Ecto.Changeset.change(user, %{avatar: nil, bio: nil, old_name: nil})
{:ok, user} = Repo.update(change)
refute user.avatar
doc = XML.parse_document(File.read!("test/fixtures/23211.atom"))
[author] = :xmerl_xpath.string('//author[1]', doc)
{:ok, user} = OStatus.find_make_or_update_user(author)
assert user.avatar["type"] == "Image"
assert user.name == old_name
assert user.bio == old_bio
{:ok, user_again} = OStatus.find_make_or_update_user(author)
assert user_again == user
end
end
describe "gathering user info from a user id" do
test "it returns user info in a hash" do
user = "shp@social.heldscal.la"
# TODO: make test local
{:ok, data} = OStatus.gather_user_info(user)
expected = %{
"hub" => "https://social.heldscal.la/main/push/hub",
"magic_key" => "RSA.wQ3i9UA0qmAxZ0WTIp4a-waZn_17Ez1pEEmqmqoooRsG1_BvpmOvLN0G2tEcWWxl2KOtdQMCiPptmQObeZeuj48mdsDZ4ArQinexY2hCCTcbV8Xpswpkb8K05RcKipdg07pnI7tAgQ0VWSZDImncL6YUGlG5YN8b5TjGOwk2VG8=.AQAB",
"name" => "shp",
"nickname" => "shp",
"salmon" => "https://social.heldscal.la/main/salmon/user/29191",
"subject" => "acct:shp@social.heldscal.la",
"topic" => "https://social.heldscal.la/api/statuses/user_timeline/29191.atom",
"uri" => "https://social.heldscal.la/user/29191",
"host" => "social.heldscal.la",
"fqn" => user,
"bio" => "cofe",
"avatar" => %{"type" => "Image", "url" => [%{"href" => "https://social.heldscal.la/avatar/29191-original-20170421154949.jpeg", "mediaType" => "image/jpeg", "type" => "Link"}]}
}
assert data == expected
end
test "it works with the uri" do
user = "https://social.heldscal.la/user/29191"
# TODO: make test local
{:ok, data} = OStatus.gather_user_info(user)
expected = %{
"hub" => "https://social.heldscal.la/main/push/hub",
"magic_key" => "RSA.wQ3i9UA0qmAxZ0WTIp4a-waZn_17Ez1pEEmqmqoooRsG1_BvpmOvLN0G2tEcWWxl2KOtdQMCiPptmQObeZeuj48mdsDZ4ArQinexY2hCCTcbV8Xpswpkb8K05RcKipdg07pnI7tAgQ0VWSZDImncL6YUGlG5YN8b5TjGOwk2VG8=.AQAB",
"name" => "shp",
"nickname" => "shp",
"salmon" => "https://social.heldscal.la/main/salmon/user/29191",
"subject" => "https://social.heldscal.la/user/29191",
"topic" => "https://social.heldscal.la/api/statuses/user_timeline/29191.atom",
"uri" => "https://social.heldscal.la/user/29191",
"host" => "social.heldscal.la",
"fqn" => user,
"bio" => "cofe",
"avatar" => %{"type" => "Image", "url" => [%{"href" => "https://social.heldscal.la/avatar/29191-original-20170421154949.jpeg", "mediaType" => "image/jpeg", "type" => "Link"}]}
}
assert data == expected
end
end
describe "fetching a status by it's HTML url" do
test "it builds a missing status from an html url" do
url = "https://shitposter.club/notice/2827873"
{:ok, [activity] } = OStatus.fetch_activity_from_url(url)
assert activity.data["actor"] == "https://shitposter.club/user/1"
assert activity.data["object"]["id"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
end
test "it works for atom notes, too" do
url = "https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056"
{:ok, [activity] } = OStatus.fetch_activity_from_url(url)
assert activity.data["actor"] == "https://social.sakamoto.gq/users/eal"
assert activity.data["object"]["id"] == url
end
end
test "insert or update a user from given data" do
user = insert(:user, %{nickname: "nick@name.de"})
data = %{ ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname }
assert {:ok, %User{}} = OStatus.insert_or_update_user(data)
end
+
+ test "it doesn't add nil in the do field" do
+ incoming = File.read!("test/fixtures/nil_mention_entry.xml")
+ {:ok, [activity]} = OStatus.handle_incoming(incoming)
+
+ assert activity.data["to"] == ["http://localhost:4001/users/atarifrosch@social.stopwatchingus-heidelberg.de/followers", "https://www.w3.org/ns/activitystreams#Public"]
+ end
end
diff --git a/test/web/web_finger/web_finger_test.exs b/test/web/web_finger/web_finger_test.exs
index 495d3d50b..38640b6d3 100644
--- a/test/web/web_finger/web_finger_test.exs
+++ b/test/web/web_finger/web_finger_test.exs
@@ -1,61 +1,76 @@
defmodule Pleroma.Web.WebFingerTest do
use Pleroma.DataCase
alias Pleroma.Web.WebFinger
import Pleroma.Factory
describe "host meta" do
test "returns a link to the xml lrdd" do
host_info = WebFinger.host_meta()
assert String.contains?(host_info, Pleroma.Web.base_url)
end
end
describe "incoming webfinger request" do
test "works for fqns" do
user = insert(:user)
{:ok, result} = WebFinger.webfinger("#{user.nickname}@#{Pleroma.Web.Endpoint.host}")
assert is_binary(result)
end
test "works for ap_ids" do
user = insert(:user)
{:ok, result} = WebFinger.webfinger(user.ap_id)
assert is_binary(result)
end
end
describe "fingering" do
test "returns the info for a user" do
user = "shp@social.heldscal.la"
- getter = fn(_url, _headers, [params: [resource: ^user]]) ->
- {:ok, %{status_code: 200, body: File.read!("test/fixtures/webfinger.xml")}}
- end
-
- {:ok, data} = WebFinger.finger(user, getter)
+ {:ok, data} = WebFinger.finger(user)
assert data["magic_key"] == "RSA.wQ3i9UA0qmAxZ0WTIp4a-waZn_17Ez1pEEmqmqoooRsG1_BvpmOvLN0G2tEcWWxl2KOtdQMCiPptmQObeZeuj48mdsDZ4ArQinexY2hCCTcbV8Xpswpkb8K05RcKipdg07pnI7tAgQ0VWSZDImncL6YUGlG5YN8b5TjGOwk2VG8=.AQAB"
assert data["topic"] == "https://social.heldscal.la/api/statuses/user_timeline/29191.atom"
assert data["subject"] == "acct:shp@social.heldscal.la"
assert data["salmon"] == "https://social.heldscal.la/main/salmon/user/29191"
end
+
+ test "it works for friendica" do
+ user = "lain@squeet.me"
+
+ {:ok, data} = WebFinger.finger(user)
+
+ end
+
+ test "it gets the xrd endpoint" do
+ {:ok, template} = WebFinger.find_lrdd_template("social.heldscal.la")
+
+ assert template == "https://social.heldscal.la/.well-known/webfinger?resource={uri}"
+ end
+
+ test "it gets the xrd endpoint for hubzilla" do
+ {:ok, template} = WebFinger.find_lrdd_template("macgirvin.com")
+
+ assert template == "https://macgirvin.com/xrd/?uri={uri}"
+ end
end
describe "ensure_keys_present" do
test "it creates keys for a user and stores them in info" do
user = insert(:user)
refute is_binary(user.info["keys"])
{:ok, user} = WebFinger.ensure_keys_present(user)
assert is_binary(user.info["keys"])
end
test "it doesn't create keys if there already are some" do
user = insert(:user, %{info: %{"keys" => "xxx"}})
{:ok, user} = WebFinger.ensure_keys_present(user)
assert user.info["keys"] == "xxx"
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 19, 3:25 AM (1 d, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1768767
Default Alt Text
(121 KB)

Event Timeline