Commit fa2610c7 authored by lain's avatar lain
Browse files

Handle incoming favorites, fetch potentially missing messages.

parent d982f04a
......@@ -41,7 +41,7 @@ def create(to, actor, context, object, additional \\ %{}, published \\ nil, loca
end
end
def like(%User{ap_id: ap_id} = user, %Object{data: %{"id" => id}} = object) do
def like(%User{ap_id: ap_id} = user, %Object{data: %{"id" => id}} = object, local \\ true) do
cond do
# There's already a like here, so return the original activity.
ap_id in (object.data["likes"] || []) ->
......@@ -59,7 +59,7 @@ def like(%User{ap_id: ap_id} = user, %Object{data: %{"id" => id}} = object) do
"context" => object.data["context"]
}
{:ok, activity} = insert(data)
{:ok, activity} = insert(data, local)
likes = [ap_id | (object.data["likes"] || [])] |> Enum.uniq
......
defmodule Pleroma.Web.OStatus do
@httpoison Application.get_env(:pleroma, :httpoison)
import Ecto.Query
import Pleroma.Web.XML
require Logger
......@@ -30,6 +32,8 @@ def handle_incoming(xml_string) do
case verb do
'http://activitystrea.ms/schema/1.0/share' ->
with {:ok, activity, retweeted_activity} <- handle_share(entry, doc), do: [activity, retweeted_activity]
'http://activitystrea.ms/schema/1.0/favorite' ->
with {:ok, activity, favorited_activity} <- handle_favorite(entry, doc), do: [activity, favorited_activity]
_ ->
case object_type do
'http://activitystrea.ms/schema/1.0/note' ->
......@@ -63,6 +67,24 @@ def handle_share(entry, doc) do
end
end
def make_favorite(_entry, doc, favorited_activity) do
with {:ok, actor} <- find_make_or_update_user(doc),
%Object{} = object <- Object.get_cached_by_ap_id(favorited_activity.data["object"]["id"]),
{:ok, activity, _object} = ActivityPub.like(actor, object, false) do
{:ok, activity}
end
end
def handle_favorite(entry, doc) do
with href when not is_nil(href) <- string_from_xpath("//activity:object[1]/link[@type=\"text/html\"]/@href", entry),
{:ok, [favorited_activity]} <- fetch_activity_from_html_url(href),
{:ok, activity} <- make_favorite(entry, doc, favorited_activity) do
{:ok, activity, favorited_activity}
else
e -> {:error, e}
end
end
def get_attachments(entry) do
:xmerl_xpath.string('/entry/link[@rel="enclosure"]', entry)
|> Enum.map(fn (enclosure) ->
......@@ -210,4 +232,30 @@ def gather_user_info(username) do
{:error, e}
end
end
# Regex-based 'parsing' so we don't have to pull in a full html parser
# It's a hack anyway. Maybe revisit this in the future
@mastodon_regex ~r/<link href='(.*)' rel='alternate' type='application\/atom\+xml'>/
@gs_regex ~r/<link title=.* href="(.*)" type="application\/atom\+xml" rel="alternate">/
def get_atom_url(body) do
cond do
Regex.match?(@mastodon_regex, body) ->
[[_, match]] = Regex.scan(@mastodon_regex, body)
{:ok, match}
Regex.match?(@gs_regex, body) ->
[[_, match]] = Regex.scan(@gs_regex, body)
{:ok, match}
true ->
Logger.debug(fn -> "Couldn't find atom link in #{inspect(body)}" end)
{:error, "Couldn't find the atom link"}
end
end
def fetch_activity_from_html_url(url) do
with {:ok, %{body: body}} <- @httpoison.get(url),
{:ok, atom_url} <- get_atom_url(body),
{:ok, %{status_code: code, body: body}} when code in 200..299 <- @httpoison.get(atom_url) do
handle_incoming(body)
end
end
end
<?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.0.2-dev">GNU social</generator>
<id>https://social.heldscal.la/api/statuses/user_timeline/23211.atom</id>
<title>lambadalambda timeline</title>
<subtitle>Updates from lambadalambda on social.heldscal.la!</subtitle>
<logo>https://social.heldscal.la/avatar/23211-96-20170416114255.jpeg</logo>
<updated>2017-05-05T09:12:53+00:00</updated>
<author>
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
<uri>https://social.heldscal.la/user/23211</uri>
<name>lambadalambda</name>
<summary>Call me Deacon Blues.</summary>
<link rel="alternate" type="text/html" href="https://social.heldscal.la/lambadalambda"/>
<link rel="avatar" type="image/jpeg" media:width="236" media:height="236" href="https://social.heldscal.la/avatar/23211-original-20170416114255.jpeg"/>
<link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/23211-96-20170416114255.jpeg"/>
<link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/23211-48-20170416114255.jpeg"/>
<link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/23211-24-20170416114257.jpeg"/>
<poco:preferredUsername>lambadalambda</poco:preferredUsername>
<poco:displayName>Constance Variable</poco:displayName>
<poco:note>Call me Deacon Blues.</poco:note>
<poco:address>
<poco:formatted>Berlin</poco:formatted>
</poco:address>
<poco:urls>
<poco:type>homepage</poco:type>
<poco:value>https://heldscal.la</poco:value>
<poco:primary>true</poco:primary>
</poco:urls>
<followers url="https://social.heldscal.la/lambadalambda/subscribers"></followers>
<statusnet:profile_info local_id="23211"></statusnet:profile_info>
</author>
<link href="https://social.heldscal.la/lambadalambda" rel="alternate" type="text/html"/>
<link href="https://social.heldscal.la/main/sup" rel="http://api.friendfeed.com/2008/03#sup" type="application/json"/>
<link href="https://social.heldscal.la/main/push/hub" rel="hub"/>
<link href="https://social.heldscal.la/main/salmon/user/23211" rel="salmon"/>
<link href="https://social.heldscal.la/main/salmon/user/23211" rel="http://salmon-protocol.org/ns/salmon-replies"/>
<link href="https://social.heldscal.la/main/salmon/user/23211" rel="http://salmon-protocol.org/ns/salmon-mention"/>
<link href="https://social.heldscal.la/api/statuses/user_timeline/23211.atom" rel="self" type="application/atom+xml"/>
<entry>
<id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2061643:2017-05-05T09:12:50+00:00</id>
<title>Favorite</title>
<content type="html">lambadalambda favorited something by moonman: @&lt;a href=&quot;https://shitposter.club/user/9655&quot; class=&quot;h-card mention&quot; title=&quot;Solidarity for Pigs&quot;&gt;neimzr4luzerz&lt;/a&gt; @&lt;a href=&quot;https://gs.smuglo.li/user/2326&quot; class=&quot;h-card mention&quot; title=&quot;Dolus_McHonest&quot;&gt;dolus&lt;/a&gt; childhood poring over Strong's concordance and a koine Greek dictionary, fast forward to 2017 and some fuckstick who translates japanese jackoff material tells me you just need to make it sound right in English</content>
<link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061828"/>
<activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb>
<published>2017-05-05T09:12:50+00:00</published>
<updated>2017-05-05T09:12:50+00:00</updated>
<activity:object>
<activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
<id>tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment</id>
<title>New comment by moonman</title>
<content type="html">@&lt;a href=&quot;https://shitposter.club/user/9655&quot; class=&quot;h-card mention&quot; title=&quot;Solidarity for Pigs&quot;&gt;neimzr4luzerz&lt;/a&gt; @&lt;a href=&quot;https://gs.smuglo.li/user/2326&quot; class=&quot;h-card mention&quot; title=&quot;Dolus_McHonest&quot;&gt;dolus&lt;/a&gt; childhood poring over Strong's concordance and a koine Greek dictionary, fast forward to 2017 and some fuckstick who translates japanese jackoff material tells me you just need to make it sound right in English</content>
<link rel="alternate" type="text/html" href="https://shitposter.club/notice/2827873"/>
<status_net notice_id="2061643"></status_net>
</activity:object>
<thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" href="https://shitposter.club/notice/2827873"></thr:in-reply-to>
<link rel="related" href="https://shitposter.club/notice/2827873"/>
<link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1061781"/>
<ostatus:conversation href="https://social.heldscal.la/conversation/1061781" local_id="1061781" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=55ead90125cd4bd4">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=55ead90125cd4bd4</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.heldscal.la/api/statuses/show/2061828.atom"/>
<link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061828.atom"/>
<statusnet:notice_info local_id="2061828" source="unknown"></statusnet:notice_info>
</entry>
</feed>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:georss="http://www.georss.org/georss" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:statusnet="http://status.net/schema/api/1/">
<activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
<id>tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment</id>
<title>New comment by moonman</title>
<content type="html">@&lt;a href=&quot;https://shitposter.club/user/9655&quot; class=&quot;h-card mention&quot; title=&quot;Solidarity for Pigs&quot;&gt;neimzr4luzerz&lt;/a&gt; @&lt;a href=&quot;https://gs.smuglo.li/user/2326&quot; class=&quot;h-card mention&quot; title=&quot;Dolus_McHonest&quot;&gt;dolus&lt;/a&gt; childhood poring over Strong's concordance and a koine Greek dictionary, fast forward to 2017 and some fuckstick who translates japanese jackoff material tells me you just need to make it sound right in English</content>
<link rel="alternate" type="text/html" href="https://shitposter.club/notice/2827873"/>
<status_net notice_id="2827873"></status_net>
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<published>2017-05-05T08:51:48+00:00</published>
<updated>2017-05-05T08:51:48+00:00</updated>
<author>
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
<uri>https://shitposter.club/user/1</uri>
<name>moonman</name>
<summary>EMAIL:shitposterclub@gmail.com XMPP: moon@talk.shitposter.club Matrix Ed25519 fingerprint: 2HuDUTEz3iFN5N3xl6PYp9xZW/EWhgbbt78SrFy4w8o</summary>
<link rel="alternate" type="text/html" href="https://shitposter.club/moonman"/>
<link rel="avatar" type="image/jpeg" media:width="1040" media:height="1040" href="https://shitposter.club/avatar/1-original-20170503024316.jpeg"/>
<link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://shitposter.club/avatar/1-96-20170503024316.jpeg"/>
<link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://shitposter.club/avatar/1-48-20170503024316.jpeg"/>
<link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://shitposter.club/avatar/1-24-20170503024318.jpeg"/>
<poco:preferredUsername>moonman</poco:preferredUsername>
<poco:displayName>Generic Enemy</poco:displayName>
<poco:note>EMAIL:shitposterclub@gmail.com XMPP: moon@talk.shitposter.club Matrix Ed25519 fingerprint: 2HuDUTEz3iFN5N3xl6PYp9xZW/EWhgbbt78SrFy4w8o</poco:note>
<poco:address>
<poco:formatted>The Moon</poco:formatted>
</poco:address>
<poco:urls>
<poco:type>homepage</poco:type>
<poco:value>https://shitposter.club/moonman</poco:value>
<poco:primary>true</poco:primary>
</poco:urls>
<followers url="https://shitposter.club/moonman/subscribers"></followers>
<statusnet:profile_info local_id="1"></statusnet:profile_info>
</author>
<thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2827849:objectType=comment" href="https://shitposter.club/notice/2827849"></thr:in-reply-to>
<link rel="related" href="https://shitposter.club/notice/2827849"/>
<link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390270"/>
<ostatus:conversation href="https://shitposter.club/conversation/1390270" local_id="1390270" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26">tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26</ostatus:conversation>
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/2326"/>
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9655"/>
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
<source>
<id>https://shitposter.club/api/statuses/user_timeline/1.atom</id>
<title>Generic Enemy</title>
<link rel="alternate" type="text/html" href="https://shitposter.club/moonman"/>
<link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/user_timeline/1.atom"/>
<link rel="license" href="https://shitposter.club/doc/tos"/>
<icon>https://shitposter.club/avatar/1-96-20170503024316.jpeg</icon>
<updated>2017-05-05T11:43:58+00:00</updated>
</source>
<link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2827873.atom"/>
<link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2827873.atom"/>
<statusnet:notice_info local_id="2827873" source="Qvitter"></statusnet:notice_info>
</entry>
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Subject>https://shitposter.club/user/1</Subject>
<Alias>acct:moonman@shitposter.club</Alias>
<Alias>https://shitposter.club/moonman</Alias>
<Alias>https://shitposter.club/index.php/user/1</Alias>
<Alias>https://shitposter.club/index.php/moonman</Alias>
<Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="https://shitposter.club/moonman"/>
<Link rel="http://gmpg.org/xfn/11" type="text/html" href="https://shitposter.club/moonman"/>
<Link rel="describedby" type="application/rdf+xml" href="https://shitposter.club/moonman/foaf"/>
<Link rel="http://apinamespace.org/atom" type="application/atomsvc+xml" href="https://shitposter.club/api/statusnet/app/service/moonman.xml"/>
<Link rel="http://apinamespace.org/twitter" href="https://shitposter.club/api/"/>
<Link rel="http://specs.openid.net/auth/2.0/provider" href="https://shitposter.club/moonman"/>
<Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="https://shitposter.club/api/statuses/user_timeline/1.atom"/>
<Link rel="magic-public-key" href="data:application/magic-public-key,RSA.4PyrQWAfiQOIxPm4yO-0XHVxMTa8cY4PETeJSjcOx9CMNqiRYNxsT9JFyAwugiwASieMGZhfUDI7Huxyjhb-tyGzlCQEJdJxcWfaRFikwwqWyzpqtQAOjJCb0vYd8gTXSQNJfpwLWQSXUQgwwi31CR3ZlAAc5vtTuWgmKEUrk3c=.AQAB"/>
<Link rel="salmon" href="https://shitposter.club/main/salmon/user/1"/>
<Link rel="http://salmon-protocol.org/ns/salmon-replies" href="https://shitposter.club/main/salmon/user/1"/>
<Link rel="http://salmon-protocol.org/ns/salmon-mention" href="https://shitposter.club/main/salmon/user/1"/>
<Link rel="http://ostatus.org/schema/1.0/subscribe" template="https://shitposter.club/main/ostatussub?profile={uri}"/>
</XRD>
......@@ -38,6 +38,13 @@ def get("https://mastodon.social/.well-known/webfinger", [Accept: "application/x
}}
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("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,
......@@ -87,6 +94,27 @@ def get("http://gs.example.org/index.php/api/statuses/user_timeline/1.atom", _bo
}}
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 get(url, body, headers) do
{:error, "Not implemented the mock response for get #{inspect(url)}"}
end
......
......@@ -96,6 +96,20 @@ test "handle incoming retweets - Mastodon, salmon" do
refute retweeted_activity.local
end
test "handle incoming favorites - GS, websub" do
incoming = File.read!("test/fixtures/favorite.xml")
{:ok, [[activity, retweeted_activity]]} = OStatus.handle_incoming(incoming)
assert activity.data["type"] == "Like"
assert activity.data["actor"] == "https://social.heldscal.la/user/23211"
assert activity.data["object"] == retweeted_activity.data["object"]["id"]
refute activity.local
assert retweeted_activity.data["type"] == "Create"
assert retweeted_activity.data["actor"] == "https://shitposter.club/user/1"
assert retweeted_activity.data["object"]["id"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
refute retweeted_activity.local
end
test "handle incoming replies" do
incoming = File.read!("test/fixtures/incoming_note_activity_answer.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
......@@ -191,4 +205,14 @@ test "it works with the uri" do
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_html_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
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment