logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git
commit: 3104367931bdd259752fb9e2b7a19ba42a72e614
parent bf181ca96850f3e5baaf8f3dcd6e11b926fcdeeb
Author: Alex Gleason <alex@alexgleason.me>
Date:   Tue, 22 Sep 2020 13:37:02 -0500

Merge remote-tracking branch 'upstream/develop' into email-fix-develop

Diffstat:

ACC-BY-4.0395+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MCHANGELOG.md32++++++++++++++++++++++++++++++++
MDockerfile2+-
MREADME.md7++++---
MSECURITY.md2+-
Mconfig/config.exs45+++++++++++++++++++++++++++++++++------------
Mconfig/description.exs87++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mconfig/test.exs7+++++--
Mdocs/API/admin_api.md163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdocs/API/pleroma_api.md16++++++++++++++++
Mdocs/administration/updating.md7++++---
Mdocs/configuration/cheatsheet.md43++++++++++++++++++++++++++++++++++---------
Minstallation/pleroma.nginx33++++++++++++++++++++-------------
Mlib/mix/pleroma.ex1+
Mlib/mix/tasks/pleroma/benchmark.ex11++++-------
Mlib/mix/tasks/pleroma/config.ex10++++++++--
Mlib/mix/tasks/pleroma/database.ex21+++++++++++++--------
Mlib/mix/tasks/pleroma/emoji.ex12++----------
Mlib/mix/tasks/pleroma/frontend.ex7+++----
Mlib/mix/tasks/pleroma/user.ex4++--
Mlib/pleroma/activity.ex7++-----
Dlib/pleroma/activity_expiration.ex74--------------------------------------------------------------------------
Mlib/pleroma/application.ex32+++++++++++++++++++++-----------
Mlib/pleroma/chat.ex10++++++++++
Mlib/pleroma/config/deprecation_warnings.ex101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Alib/pleroma/config/oban.ex34++++++++++++++++++++++++++++++++++
Alib/pleroma/ecto_type/activity_pub/object_validators/emoji.ex34++++++++++++++++++++++++++++++++++
Mlib/pleroma/gun/conn.ex14+++++++-------
Mlib/pleroma/gun/connection_pool/worker.ex45++++++++++++++++++++++++---------------------
Alib/pleroma/helpers/media_helper.ex150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/helpers/qt_fast_start.ex131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/helpers/uri_helper.ex14+++++++++-----
Mlib/pleroma/http/adapter_helper.ex6+-----
Mlib/pleroma/http/adapter_helper/gun.ex23++++++-----------------
Mlib/pleroma/http/adapter_helper/hackney.ex15+++++++++------
Mlib/pleroma/http/ex_aws.ex2+-
Mlib/pleroma/http/http.ex43++++++++++++++++++-------------------------
Mlib/pleroma/http/tzdata.ex4++--
Mlib/pleroma/instances/instance.ex16++++++----------
Mlib/pleroma/mfa/token.ex71+++++++++++++++++++++++++++++++++++------------------------------------
Mlib/pleroma/migration_helper/notification_backfill.ex15+++++++--------
Mlib/pleroma/moderation_log.ex24++++++++++++++++++++++++
Mlib/pleroma/notification.ex12++++++++++++
Mlib/pleroma/object/containment.ex7-------
Mlib/pleroma/object/fetcher.ex67++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mlib/pleroma/plugs/oauth_scopes_plug.ex2+-
Mlib/pleroma/repo.ex23+++++++++++++++++++++--
Dlib/pleroma/repo_streamer.ex34----------------------------------
Mlib/pleroma/reverse_proxy/client/tesla.ex2+-
Mlib/pleroma/reverse_proxy/reverse_proxy.ex5+++++
Mlib/pleroma/signature.ex6+++---
Mlib/pleroma/stats.ex77++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mlib/pleroma/telemetry/logger.ex18++++++++++++++++--
Alib/pleroma/tesla/middleware/connection_pool.ex50++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/pleroma/tesla/middleware/follow_redirects.ex110-------------------------------------------------------------------------------
Mlib/pleroma/user.ex89+++++++++++++++++++++++--------------------------------------------------------
Alib/pleroma/user/import.ex85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/user/search.ex5+++++
Mlib/pleroma/web/activity_pub/activity_pub.ex90+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mlib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex4++--
Alib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex22++++++++++------------
Mlib/pleroma/web/activity_pub/object_validator.ex31++++++++++++++++++++++++-------
Alib/pleroma/web/activity_pub/object_validators/article_note_validator.ex106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/web/activity_pub/object_validators/attachment_validator.ex21+++++++++++++++++++--
Dlib/pleroma/web/activity_pub/object_validators/audio_validator.ex106-------------------------------------------------------------------------------
Alib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex2+-
Mlib/pleroma/web/activity_pub/object_validators/common_fixes.ex13+++++++++++--
Mlib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex8+++++---
Mlib/pleroma/web/activity_pub/object_validators/event_validator.ex5+++--
Dlib/pleroma/web/activity_pub/object_validators/note_validator.ex66------------------------------------------------------------------
Mlib/pleroma/web/activity_pub/object_validators/question_validator.ex9+++++----
Dlib/pleroma/web/activity_pub/object_validators/url_object_validator.ex24------------------------
Mlib/pleroma/web/activity_pub/publisher.ex34+++++++++++++++++++++++-----------
Mlib/pleroma/web/activity_pub/side_effects.ex7+------
Mlib/pleroma/web/activity_pub/transmogrifier.ex48+++++++-----------------------------------------
Mlib/pleroma/web/admin_api/controllers/admin_api_controller.ex22++++++++++++++++++++--
Alib/pleroma/web/admin_api/controllers/chat_controller.ex85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/admin_api/controllers/instance_document_controller.ex41+++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/admin_api/views/chat_view.ex30++++++++++++++++++++++++++++++
Mlib/pleroma/web/admin_api/views/status_view.ex3++-
Mlib/pleroma/web/api_spec.ex13+++++++++----
Mlib/pleroma/web/api_spec/helpers.ex6+++++-
Mlib/pleroma/web/api_spec/operations/account_operation.ex7+++++--
Alib/pleroma/web/api_spec/operations/admin/chat_operation.ex96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/web/api_spec/operations/custom_emoji_operation.ex2+-
Mlib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex2+-
Mlib/pleroma/web/api_spec/operations/list_operation.ex21++++++++++++++-------
Alib/pleroma/web/api_spec/operations/user_import_operation.ex80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/web/api_spec/schemas/chat_message.ex3++-
Mlib/pleroma/web/api_spec/schemas/scheduled_status.ex4++--
Mlib/pleroma/web/auth/pleroma_authenticator.ex2+-
Mlib/pleroma/web/common_api/activity_draft.ex2+-
Mlib/pleroma/web/common_api/common_api.ex25+++++++++++++++++++++----
Alib/pleroma/web/fed_sockets/fed_registry.ex185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/fed_sockets/fed_socket.ex137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/fed_sockets/fed_sockets.ex185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/fed_sockets/fetch_registry.ex151++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/fed_sockets/incoming_handler.ex88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/fed_sockets/ingester_worker.ex33+++++++++++++++++++++++++++++++++
Alib/pleroma/web/fed_sockets/outgoing_handler.ex151++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/fed_sockets/socket_info.ex52++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/web/fed_sockets/supervisor.ex59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/web/federator/federator.ex16+++++++++++-----
Alib/pleroma/web/instance_document.ex62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/web/mastodon_api/controllers/list_controller.ex6+++++-
Mlib/pleroma/web/mastodon_api/views/account_view.ex12+++++++-----
Mlib/pleroma/web/mastodon_api/views/status_view.ex33++++++++-------------------------
Mlib/pleroma/web/mastodon_api/websocket_handler.ex10+++++-----
Mlib/pleroma/web/media_proxy/invalidation.ex4+++-
Mlib/pleroma/web/media_proxy/media_proxy.ex87++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mlib/pleroma/web/media_proxy/media_proxy_controller.ex195+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mlib/pleroma/web/metadata/opengraph.ex2+-
Mlib/pleroma/web/metadata/restrict_indexing.ex7+++----
Mlib/pleroma/web/metadata/twitter_card.ex2+-
Mlib/pleroma/web/metadata/utils.ex2+-
Mlib/pleroma/web/oauth/oauth_controller.ex8++++----
Mlib/pleroma/web/oauth/token.ex25+++++++++++++++++--------
Dlib/pleroma/web/oauth/token/clean_worker.ex38--------------------------------------
Mlib/pleroma/web/oauth/token/query.ex6------
Mlib/pleroma/web/oauth/token/strategy/refresh_token.ex2+-
Mlib/pleroma/web/pleroma_api/controllers/chat_controller.ex9++-------
Alib/pleroma/web/pleroma_api/controllers/user_import_controller.ex61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/pleroma/web/pleroma_api/views/scrobble_view.ex4++--
Mlib/pleroma/web/rel_me.ex15+++------------
Mlib/pleroma/web/rich_media/helpers.ex23+++++++----------------
Mlib/pleroma/web/rich_media/parser.ex72+++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mlib/pleroma/web/router.ex18+++++++++++++++---
Mlib/pleroma/web/streamer/streamer.ex70+++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mlib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex2+-
Mlib/pleroma/web/twitter_api/controllers/util_controller.ex35-----------------------------------
Mlib/pleroma/workers/background_worker.ex24++++--------------------
Dlib/pleroma/workers/cron/clear_oauth_token_worker.ex23-----------------------
Dlib/pleroma/workers/cron/purge_expired_activities_worker.ex48------------------------------------------------
Dlib/pleroma/workers/cron/stats_worker.ex17-----------------
Alib/pleroma/workers/purge_expired_activity.ex72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/pleroma/workers/purge_expired_token.ex29+++++++++++++++++++++++++++++
Mmix.exs8+++++---
Mmix.lock8+++++---
Apriv/gettext/es/LC_MESSAGES/errors.po586+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apriv/gettext/zh_Hans/LC_MESSAGES/errors.po580+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apriv/repo/migrations/20200824115541_rename_activity_expiration_setting.exs13+++++++++++++
Apriv/repo/migrations/20200825061316_move_activity_expirations_to_oban.exs28++++++++++++++++++++++++++++
Apriv/repo/migrations/20200825093037_drop_activity_expirations_table.exs7+++++++
Apriv/repo/migrations/20200831142509_chat_constraints.exs22++++++++++++++++++++++
Apriv/repo/migrations/20200901061256_ensure_bio_is_string.exs7+++++++
Apriv/repo/migrations/20200901061637_bio_set_not_null.exs10++++++++++
Apriv/repo/migrations/20200905082737_rename_await_up_timeout_in_connections_pool.exs13+++++++++++++
Apriv/repo/migrations/20200905091427_rename_timeout_in_pools.exs19+++++++++++++++++++
Apriv/repo/migrations/20200906072147_remove_cron_stats_worker_from_oban_config.exs19+++++++++++++++++++
Apriv/repo/migrations/20200907084956_remove_cron_clear_oauth_token_worker_from_oban_config.exs19+++++++++++++++++++
Apriv/repo/migrations/20200907092050_move_tokens_expiration_into_oban.exs38++++++++++++++++++++++++++++++++++++++
Apriv/repo/migrations/20200910113106_remove_managed_config_from_db.exs27+++++++++++++++++++++++++++
Apriv/repo/migrations/20200911055909_remove_cron_jobs.exs20++++++++++++++++++++
Apriv/repo/migrations/20200914105638_delete_notification_without_activity.exs30++++++++++++++++++++++++++++++
Apriv/repo/migrations/20200914105800_add_notification_constraints.exs23+++++++++++++++++++++++
Dtest/activity_expiration_test.exs55-------------------------------------------------------
Mtest/activity_test.exs9---------
Mtest/chat_test.exs22++++++++++++++++++++++
Mtest/config/deprecation_warnings_test.exs59+++++++++++++++++++++++++++++++++++++++++++++++++++++------
Dtest/fixtures/23211.atom508-------------------------------------------------------------------------------
Atest/fixtures/custom_instance_panel.html2++
Dtest/fixtures/cw_retweet.xml68--------------------------------------------------------------------
Dtest/fixtures/delete.xml39---------------------------------------
Dtest/fixtures/dm.xml27---------------------------
Dtest/fixtures/favorite.xml65-----------------------------------------------------------------
Dtest/fixtures/favorite_with_local_note.xml64----------------------------------------------------------------
Dtest/fixtures/follow.xml68--------------------------------------------------------------------
Atest/fixtures/image.gif0
Atest/fixtures/image.png0
Dtest/fixtures/incoming_note_activity.xml42------------------------------------------
Dtest/fixtures/incoming_note_activity_answer.xml42------------------------------------------
Dtest/fixtures/incoming_reply_mastodon.xml29-----------------------------
Dtest/fixtures/incoming_websub_gnusocial_attachments.xml59-----------------------------------------------------------
Dtest/fixtures/lambadalambda.atom479-------------------------------------------------------------------------------
Dtest/fixtures/mastodon-note-cw.xml39---------------------------------------
Dtest/fixtures/mastodon-note-unlisted.xml38--------------------------------------
Dtest/fixtures/mastodon-problematic.xml72------------------------------------------------------------------------
Dtest/fixtures/mastodon_conversation.xml30------------------------------
Dtest/fixtures/nil_mention_entry.xml52----------------------------------------------------
Dtest/fixtures/ostatus_incoming_post.xml57---------------------------------------------------------
Dtest/fixtures/ostatus_incoming_post_tag.xml59-----------------------------------------------------------
Dtest/fixtures/ostatus_incoming_reply.xml60------------------------------------------------------------
Dtest/fixtures/share-gs-local.xml99-------------------------------------------------------------------------------
Dtest/fixtures/share-gs.xml99-------------------------------------------------------------------------------
Dtest/fixtures/share.xml54------------------------------------------------------
Dtest/fixtures/tesla_mock/7369654.atom44--------------------------------------------
Mtest/fixtures/tesla_mock/admin@mastdon.example.org.json45+++++++++++++++++++++++++++------------------
Dtest/fixtures/tesla_mock/atarifrosch_feed.xml473-------------------------------------------------------------------------------
Dtest/fixtures/tesla_mock/emelie.atom306-------------------------------------------------------------------------------
Mtest/fixtures/tesla_mock/framatube.org-video.json4++--
Dtest/fixtures/tesla_mock/http__gs.example.org_index.php_api_statuses_user_timeline_1.atom.xml460-------------------------------------------------------------------------------
Dtest/fixtures/tesla_mock/https___mamot.fr_users_Skruyb.atom342-------------------------------------------------------------------------------
Dtest/fixtures/tesla_mock/https___mastodon.social_users_lambadalambda.atom464-------------------------------------------------------------------------------
Mtest/fixtures/tesla_mock/https___osada.macgirvin.com_channel_mike.json4+++-
Dtest/fixtures/tesla_mock/https___pawoo.net_users_pekorino.atom231-------------------------------------------------------------------------------
Dtest/fixtures/tesla_mock/https___pleroma.soykaf.com_users_lain_feed.atom.xml2--
Dtest/fixtures/tesla_mock/https___shitposter.club_api_statuses_show_2827873.atom.xml54------------------------------------------------------
Dtest/fixtures/tesla_mock/https___shitposter.club_api_statuses_user_timeline_1.atom.xml454-------------------------------------------------------------------------------
Dtest/fixtures/tesla_mock/https___shitposter.club_notice_2827873.json2--
Dtest/fixtures/tesla_mock/https___social.heldscal.la_api_statuses_user_timeline_23211.atom.xml591-------------------------------------------------------------------------------
Dtest/fixtures/tesla_mock/https___social.heldscal.la_api_statuses_user_timeline_29191.atom.xml719-------------------------------------------------------------------------------
Dtest/fixtures/tesla_mock/sakamoto.atom2--
Dtest/fixtures/tesla_mock/sakamoto_eal_feed.atom2--
Dtest/fixtures/tesla_mock/shp@pleroma.soykaf.com.feed2--
Dtest/fixtures/tesla_mock/spc_5381.atom438-------------------------------------------------------------------------------
Atest/fixtures/tesla_mock/wedistribute-create-article.json2++
Dtest/fixtures/unfollow.xml68--------------------------------------------------------------------
Mtest/integration/mastodon_websocket_test.exs2+-
Mtest/marker_test.exs4++--
Mtest/notification_test.exs8+++++---
Mtest/object/fetcher_test.exs24++++++++++++++++++------
Mtest/plugs/oauth_plug_test.exs2+-
Mtest/repo_test.exs32+++++++++++++++++++++++++++++++-
Mtest/stats_test.exs21++++++++++++---------
Mtest/support/data_case.ex15+++++++++++++++
Mtest/support/factory.ex20+-------------------
Mtest/support/http_request_mock.ex174-------------------------------------------------------------------------------
Mtest/tasks/config_test.exs13+++++++++++++
Mtest/tasks/database_test.exs64+++++++++++++++++++++++++++++++++++-----------------------------
Mtest/tasks/frontend_test.exs9++++++++-
Atest/user/import_test.exs76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/user_search_test.exs8++++++++
Mtest/user_test.exs51+++++++++++++--------------------------------------
Mtest/web/activity_pub/activity_pub_test.exs82++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mtest/web/activity_pub/mrf/activity_expiration_policy_test.exs8++++----
Atest/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs2++
Atest/web/activity_pub/object_validators/article_note_validator_test.exs35+++++++++++++++++++++++++++++++++++
Mtest/web/activity_pub/object_validators/chat_validation_test.exs1+
Dtest/web/activity_pub/object_validators/note_validator_test.exs35-----------------------------------
Atest/web/activity_pub/transmogrifier/article_handling_test.exs75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/web/activity_pub/transmogrifier/question_handling_test.exs51+++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/web/activity_pub/transmogrifier/video_handling_test.exs93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/web/activity_pub/transmogrifier_test.exs185++++++-------------------------------------------------------------------------
Mtest/web/admin_api/controllers/admin_api_controller_test.exs52+++++++++++++++++++++++++++++++++++++++++++++++++++-
Atest/web/admin_api/controllers/chat_controller_test.exs219+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/web/admin_api/controllers/instance_document_controller_test.exs106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/web/admin_api/search_test.exs9+++++++++
Mtest/web/common_api/common_api_test.exs99++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Atest/web/fed_sockets/fed_registry_test.exs124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/web/fed_sockets/fetch_registry_test.exs67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/web/fed_sockets/socket_info_test.exs118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/web/instances/instance_test.exs79++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mtest/web/mastodon_api/controllers/account_controller_test.exs5++++-
Mtest/web/mastodon_api/controllers/list_controller_test.exs20+++++++++++++++++++-
Mtest/web/mastodon_api/controllers/marker_controller_test.exs2+-
Mtest/web/mastodon_api/controllers/search_controller_test.exs12++++++------
Mtest/web/mastodon_api/controllers/status_controller_test.exs101+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mtest/web/mastodon_api/controllers/timeline_controller_test.exs12++++++++++--
Mtest/web/mastodon_api/views/account_view_test.exs47+++++++++++++++++++++++++----------------------
Mtest/web/media_proxy/media_proxy_controller_test.exs312+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mtest/web/media_proxy/media_proxy_test.exs73++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mtest/web/metadata/metadata_test.exs21++++++++++++++++++---
Mtest/web/metadata/restrict_indexing_test.exs8+++++++-
Mtest/web/oauth/token_test.exs13-------------
Atest/web/pleroma_api/controllers/user_import_controller_test.exs235+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/web/push/impl_test.exs18++++++++++++++++++
Mtest/web/rich_media/parser_test.exs4+---
Mtest/web/streamer/streamer_test.exs394+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mtest/web/twitter_api/password_controller_test.exs4++--
Mtest/web/twitter_api/remote_follow_controller_test.exs4++--
Mtest/web/twitter_api/util_controller_test.exs166+------------------------------------------------------------------------------
Dtest/workers/cron/clear_oauth_token_worker_test.exs22----------------------
Dtest/workers/cron/purge_expired_activities_worker_test.exs84-------------------------------------------------------------------------------
Atest/workers/purge_expired_activity_test.exs59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/workers/purge_expired_token_test.exs51+++++++++++++++++++++++++++++++++++++++++++++++++++
269 files changed, 8638 insertions(+), 9321 deletions(-)

diff --git a/CC-BY-4.0 b/CC-BY-4.0 @@ -0,0 +1,395 @@ +Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## Unreleased + +### Added +- Experimental websocket-based federation between Pleroma instances. + +### Changed + +- Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated. +- Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated. +- The `discoverable` field in the `User` struct will now add a NOINDEX metatag to profile pages when false. +- Users with the `discoverable` field set to false will not show up in searches. +- Minimum lifetime for ephmeral activities changed to 10 minutes and made configurable (`:min_lifetime` option). + +### Added +- Media preview proxy (requires media proxy be enabled; see `:media_preview_proxy` config for more details). +- Pleroma API: Importing the mutes users from CSV files. + +### Removed + +- **Breaking:** `Pleroma.Workers.Cron.StatsWorker` setting from Oban `:crontab` (moved to a simpler implementation). +- **Breaking:** `Pleroma.Workers.Cron.ClearOauthTokenWorker` setting from Oban `:crontab` (moved to scheduled jobs). +- **Breaking:** `Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker` setting from Oban `:crontab` (moved to scheduled jobs). +- Removed `:managed_config` option. In practice, it was accidentally removed with 2.0.0 release when frontends were +switched to a new configuration mechanism, however it was not officially removed until now. + + ## [2.1.2] - 2020-09-17 ### Security @@ -40,6 +66,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Rich media failure tracking (along with `:failure_backoff` option). +<details> + <summary>Admin API Changes</summary> + +- Add `PATCH /api/pleroma/admin/instance_document/:document_name` to modify the Terms of Service and Instance Panel HTML pages via Admin API +</details> + ### Fixed - Default HTTP adapter not respecting pool setting, leading to possible OOM. - Fixed uploading webp images when the Exiftool Upload Filter is enabled by skipping them diff --git a/Dockerfile b/Dockerfile @@ -31,7 +31,7 @@ LABEL maintainer="ops@pleroma.social" \ ARG HOME=/opt/pleroma ARG DATA=/var/lib/pleroma -RUN echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\ +RUN echo "https://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\ apk update &&\ apk add exiftool imagemagick ncurses postgresql-client &&\ adduser --system --shell /bin/false --home ${HOME} pleroma &&\ diff --git a/README.md b/README.md @@ -18,15 +18,16 @@ If you are running Linux (glibc or musl) on x86/arm, the recommended way to inst ### From Source If your platform is not supported, or you just want to be able to edit the source code easily, you may install Pleroma from source. -- [Debian-based](https://docs-develop.pleroma.social/backend/installation/debian_based_en/) -- [Debian-based (jp)](https://docs-develop.pleroma.social/backend/installation/debian_based_jp/) - [Alpine Linux](https://docs-develop.pleroma.social/backend/installation/alpine_linux_en/) - [Arch Linux](https://docs-develop.pleroma.social/backend/installation/arch_linux_en/) +- [CentOS 7](https://docs-develop.pleroma.social/backend/installation/centos7_en/) +- [Debian-based](https://docs-develop.pleroma.social/backend/installation/debian_based_en/) +- [Debian-based (jp)](https://docs-develop.pleroma.social/backend/installation/debian_based_jp/) +- [FreeBSD](https://docs-develop.pleroma.social/backend/installation/freebsd_en/) - [Gentoo Linux](https://docs-develop.pleroma.social/backend/installation/gentoo_en/) - [NetBSD](https://docs-develop.pleroma.social/backend/installation/netbsd_en/) - [OpenBSD](https://docs-develop.pleroma.social/backend/installation/openbsd_en/) - [OpenBSD (fi)](https://docs-develop.pleroma.social/backend/installation/openbsd_fi/) -- [CentOS 7](https://docs-develop.pleroma.social/backend/installation/centos7_en/) ### OS/Distro packages Currently Pleroma is not packaged by any OS/Distros, but if you want to package it for one, we can guide you through the process on our [community channels](#community-channels). If you want to change default options in your Pleroma package, please **discuss it with us first**. diff --git a/SECURITY.md b/SECURITY.md @@ -6,7 +6,7 @@ Currently, Pleroma offers bugfixes and security patches only for the latest mino | Version | Support |---------| -------- -| 2.0 | Bugfixes and security patches +| 2.1 | Bugfixes and security patches ## Reporting a vulnerability diff --git a/config/config.exs b/config/config.exs @@ -130,6 +130,7 @@ config :pleroma, Pleroma.Web.Endpoint, dispatch: [ {:_, [ + {"/api/fedsocket/v1", Pleroma.Web.FedSockets.IncomingHandler, []}, {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, {"/websocket", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, @@ -148,6 +149,16 @@ config :pleroma, Pleroma.Web.Endpoint, "SameSite=Lax" ] +config :pleroma, :fed_sockets, + enabled: false, + connection_duration: :timer.hours(8), + rejection_duration: :timer.minutes(15), + fed_socket_fetches: [ + default: 12_000, + interval: 3_000, + lazy: false + ] + # Configures Elixir's Logger config :logger, :console, level: :debug, @@ -216,7 +227,6 @@ config :pleroma, :instance, allow_relay: true, public: true, quarantined_instances: [], - managed_config: true, static_dir: "instance/static/", allowed_post_formats: [ "text/plain", @@ -424,6 +434,8 @@ config :pleroma, :media_proxy, proxy_opts: [ redirect_on_failure: false, max_body_length: 25 * 1_048_576, + # Note: max_read_duration defaults to Pleroma.ReverseProxy.max_read_duration_default/1 + max_read_duration: 30_000, http: [ follow_redirect: true, pool: :media @@ -438,6 +450,14 @@ config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http, config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, script_path: nil +# Note: media preview proxy depends on media proxy to be enabled +config :pleroma, :media_preview_proxy, + enabled: false, + thumbnail_max_width: 600, + thumbnail_max_height: 600, + image_quality: 85, + min_content_length: 100 * 1024 + config :pleroma, :chat, enabled: true config :phoenix, :format_encoders, json: Jason @@ -530,8 +550,10 @@ config :pleroma, Oban, log: false, queues: [ activity_expiration: 10, + token_expiration: 5, federator_incoming: 50, federator_outgoing: 50, + ingestion_queue: 50, web_push: 50, mailer: 10, transmogrifier: 20, @@ -543,9 +565,6 @@ config :pleroma, Oban, ], plugins: [Oban.Plugins.Pruner], crontab: [ - {"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker}, - {"0 * * * *", Pleroma.Workers.Cron.StatsWorker}, - {"* * * * *", Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker}, {"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker}, {"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker} ] @@ -656,7 +675,7 @@ config :pleroma, :rate_limit, account_confirmation_resend: {8_640_000, 5}, ap_routes: {60_000, 15} -config :pleroma, Pleroma.ActivityExpiration, enabled: true +config :pleroma, Pleroma.Workers.PurgeExpiredActivity, enabled: true, min_lifetime: 600 config :pleroma, Pleroma.Plugs.RemoteIp, enabled: true @@ -670,7 +689,7 @@ config :pleroma, :static_fe, enabled: false # With no frontend configuration, the bundled files from the `static` directory will # be used. # -# config :pleroma, :frontends, +# config :pleroma, :frontends, # primary: %{"name" => "pleroma-fe", "ref" => "develop"}, # admin: %{"name" => "admin-fe", "ref" => "stable"}, # available: %{...} @@ -734,28 +753,28 @@ config :pleroma, :connections_pool, max_connections: 250, max_idle_time: 30_000, retry: 0, - await_up_timeout: 5_000 + connect_timeout: 5_000 config :pleroma, :pools, federation: [ size: 50, max_waiting: 10, - timeout: 10_000 + recv_timeout: 10_000 ], media: [ size: 50, - max_waiting: 10, - timeout: 10_000 + max_waiting: 20, + recv_timeout: 15_000 ], upload: [ size: 25, max_waiting: 5, - timeout: 15_000 + recv_timeout: 15_000 ], default: [ size: 10, max_waiting: 2, - timeout: 5_000 + recv_timeout: 5_000 ] config :pleroma, :hackney_pools, @@ -790,6 +809,8 @@ config :tzdata, :http_client, Pleroma.HTTP.Tzdata config :ex_aws, http_client: Pleroma.HTTP.ExAws +config :web_push_encryption, http_client: Pleroma.HTTP + config :pleroma, :instances_favicons, enabled: false config :floki, :html_parser, Floki.HTMLParser.FastHtml diff --git a/config/description.exs b/config/description.exs @@ -272,6 +272,19 @@ config :pleroma, :config_description, [ }, %{ group: :pleroma, + key: :fed_sockets, + type: :group, + description: "Websocket based federation", + children: [ + %{ + key: :enabled, + type: :boolean, + description: "Enable FedSockets" + } + ] + }, + %{ + group: :pleroma, key: Pleroma.Emails.Mailer, type: :group, description: "Mailer-related settings", @@ -765,12 +778,6 @@ config :pleroma, :config_description, [ ] }, %{ - key: :managed_config, - type: :boolean, - description: - "Whenether the config for pleroma-fe is configured in this config or in static/config.json" - }, - %{ key: :static_dir, type: :string, description: "Instance static directory", @@ -1880,6 +1887,7 @@ config :pleroma, :config_description, [ suggestions: [ redirect_on_failure: false, max_body_length: 25 * 1_048_576, + max_read_duration: 30_000, http: [ follow_redirect: true, pool: :media @@ -1901,6 +1909,11 @@ config :pleroma, :config_description, [ "specified length. It is validated with the `content-length` header and also verified when proxying." }, %{ + key: :max_read_duration, + type: :integer, + description: "Timeout (in milliseconds) of GET request to remote URI." + }, + %{ key: :http, label: "HTTP", type: :keyword, @@ -1948,6 +1961,43 @@ config :pleroma, :config_description, [ }, %{ group: :pleroma, + key: :media_preview_proxy, + type: :group, + description: "Media preview proxy", + children: [ + %{ + key: :enabled, + type: :boolean, + description: + "Enables proxying of remote media preview to the instance's proxy. Requires enabled media proxy." + }, + %{ + key: :thumbnail_max_width, + type: :integer, + description: + "Max width of preview thumbnail for images (video preview always has original dimensions)." + }, + %{ + key: :thumbnail_max_height, + type: :integer, + description: + "Max height of preview thumbnail for images (video preview always has original dimensions)." + }, + %{ + key: :image_quality, + type: :integer, + description: "Quality of the output. Ranges from 0 (min quality) to 100 (max quality)." + }, + %{ + key: :min_content_length, + type: :integer, + description: + "Min content length to perform preview, in bytes. If greater than 0, media smaller in size will be served as is, without thumbnailing." + } + ] + }, + %{ + group: :pleroma, key: Pleroma.Web.MediaProxy.Invalidation.Http, type: :group, description: "HTTP invalidate settings", @@ -2290,9 +2340,6 @@ config :pleroma, :config_description, [ type: {:list, :tuple}, description: "Settings for cron background jobs", suggestions: [ - {"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker}, - {"0 * * * *", Pleroma.Workers.Cron.StatsWorker}, - {"* * * * *", Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker}, {"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker}, {"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker} ] @@ -2398,7 +2445,7 @@ config :pleroma, :config_description, [ %{ group: :pleroma, key: Pleroma.Formatter, - label: "Auto Linker", + label: "Linkify", type: :group, description: "Configuration for Pleroma's link formatter which parses mentions, hashtags, and URLs.", @@ -2475,14 +2522,20 @@ config :pleroma, :config_description, [ }, %{ group: :pleroma, - key: Pleroma.ActivityExpiration, + key: Pleroma.Workers.PurgeExpiredActivity, type: :group, - description: "Expired activity settings", + description: "Expired activities settings", children: [ %{ key: :enabled, type: :boolean, - description: "Whether expired activities will be sent to the job queue to be deleted" + description: "Enables expired activities addition & deletion" + }, + %{ + key: :min_lifetime, + type: :integer, + description: "Minimum lifetime for ephemeral activity (in seconds)", + suggestions: [600] } ] }, @@ -3378,7 +3431,7 @@ config :pleroma, :config_description, [ suggestions: [250] }, %{ - key: :await_up_timeout, + key: :connect_timeout, type: :integer, description: "Timeout while `gun` will wait until connection is up. Default: 5000ms.", suggestions: [5000] @@ -3416,6 +3469,12 @@ config :pleroma, :config_description, [ description: "Maximum number of requests waiting for other requests to finish. After this number is reached, the pool will start returning errrors when a new request is made", suggestions: [10] + }, + %{ + key: :recv_timeout, + type: :integer, + description: "Timeout for the pool while gun will wait for response", + suggestions: [10_000] } ] } diff --git a/config/test.exs b/config/test.exs @@ -19,6 +19,11 @@ config :logger, :console, level: :warn, format: "\n[$level] $message\n" +config :pleroma, :fed_sockets, + enabled: false, + connection_duration: 5, + rejection_duration: 5 + config :pleroma, :auth, oauth_consumer_strategies: [] config :pleroma, Pleroma.Upload, @@ -114,8 +119,6 @@ config :pleroma, Pleroma.Plugs.RemoteIp, enabled: false config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true -config :pleroma, :instances_favicons, enabled: false - config :pleroma, Pleroma.Uploaders.S3, bucket: nil, streaming_enabled: true, diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md @@ -1334,3 +1334,166 @@ Loads json generated from `config/descriptions.exs`. { } ``` + +## GET /api/pleroma/admin/users/:nickname/chats + +### List a user's chats + +- Params: None + +- Response: + +```json +[ + { + "sender": { + "id": "someflakeid", + "username": "somenick", + ... + }, + "receiver": { + "id": "someflakeid", + "username": "somenick", + ... + }, + "id" : "1", + "unread" : 2, + "last_message" : {...}, // The last message in that chat + "updated_at": "2020-04-21T15:11:46.000Z" + } +] +``` + +## GET /api/pleroma/admin/chats/:chat_id + +### View a single chat + +- Params: None + +- Response: + +```json +{ + "sender": { + "id": "someflakeid", + "username": "somenick", + ... + }, + "receiver": { + "id": "someflakeid", + "username": "somenick", + ... + }, + "id" : "1", + "unread" : 2, + "last_message" : {...}, // The last message in that chat + "updated_at": "2020-04-21T15:11:46.000Z" +} +``` + +## GET /api/pleroma/admin/chats/:chat_id/messages + +### List the messages in a chat + +- Params: `max_id`, `min_id` + +- Response: + +```json +[ + { + "account_id": "someflakeid", + "chat_id": "1", + "content": "Check this out :firefox:", + "created_at": "2020-04-21T15:11:46.000Z", + "emojis": [ + { + "shortcode": "firefox", + "static_url": "https://dontbulling.me/emoji/Firefox.gif", + "url": "https://dontbulling.me/emoji/Firefox.gif", + "visible_in_picker": false + } + ], + "id": "13", + "unread": true + }, + { + "account_id": "someflakeid", + "chat_id": "1", + "content": "Whats' up?", + "created_at": "2020-04-21T15:06:45.000Z", + "emojis": [], + "id": "12", + "unread": false + } +] +``` + +## DELETE /api/pleroma/admin/chats/:chat_id/messages/:message_id + +### Delete a single message + +- Params: None + +- Response: + +```json +{ + "account_id": "someflakeid", + "chat_id": "1", + "content": "Check this out :firefox:", + "created_at": "2020-04-21T15:11:46.000Z", + "emojis": [ + { + "shortcode": "firefox", + "static_url": "https://dontbulling.me/emoji/Firefox.gif", + "url": "https://dontbulling.me/emoji/Firefox.gif", + "visible_in_picker": false + } + ], + "id": "13", + "unread": false +} +``` + +## `GET /api/pleroma/admin/instance_document/:document_name` + +### Get an instance document + +- Authentication: required + +- Response: + +Returns the content of the document + +```html +<h1>Instance panel</h1> +``` + +## `PATCH /api/pleroma/admin/instance_document/:document_name` +- Params: + - `file` (the file to be uploaded, using multipart form data.) + +### Update an instance document + +- Authentication: required + +- Response: + +``` json +{ + "url": "https://example.com/instance/panel.html" +} +``` + +## `DELETE /api/pleroma/admin/instance_document/:document_name` + +### Delete an instance document + +- Response: + +``` json +{ + "url": "https://example.com/instance/panel.html" +} +``` diff --git a/docs/API/pleroma_api.md b/docs/API/pleroma_api.md @@ -44,6 +44,22 @@ Request parameters can be passed via [query strings](https://en.wikipedia.org/wi * Response: HTTP 200 on success, 500 on error * Note: Users that can't be followed are silently skipped. +## `/api/pleroma/blocks_import` +### Imports your blocks. +* Method: `POST` +* Authentication: required +* Params: + * `list`: STRING or FILE containing a whitespace-separated list of accounts to block +* Response: HTTP 200 on success, 500 on error + +## `/api/pleroma/mutes_import` +### Imports your mutes. +* Method: `POST` +* Authentication: required +* Params: + * `list`: STRING or FILE containing a whitespace-separated list of accounts to mute +* Response: HTTP 200 on success, 500 on error + ## `/api/pleroma/captcha` ### Get a new captcha * Method: `GET` diff --git a/docs/administration/updating.md b/docs/administration/updating.md @@ -18,9 +18,10 @@ su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate" 1. Go to the working directory of Pleroma (default is `/opt/pleroma`) 2. Run `git pull`. This pulls the latest changes from upstream. -3. Run `mix deps.get`. This pulls in any new dependencies. +3. Run `mix deps.get` [^1]. This pulls in any new dependencies. 4. Stop the Pleroma service. -5. Run `mix ecto.migrate`[^1]. This task performs database migrations, if there were any. +5. Run `mix ecto.migrate` [^1] [^2]. This task performs database migrations, if there were any. 6. Start the Pleroma service. -[^1]: Prefix with `MIX_ENV=prod` to run it using the production config file. +[^1]: Depending on which install guide you followed (for example on Debian/Ubuntu), you want to run `mix` tasks as `pleroma` user by adding `sudo -Hu pleroma` before the command. +[^2]: Prefix with `MIX_ENV=prod` to run it using the production config file. diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md @@ -18,7 +18,7 @@ To add configuration to your config file, you can copy it from the base config. * `notify_email`: Email used for notifications. * `description`: The instance’s description, can be seen in nodeinfo and ``/api/v1/instance``. * `limit`: Posts character limit (CW/Subject included in the counter). -* `discription_limit`: The character limit for image descriptions. +* `description_limit`: The character limit for image descriptions. * `chat_limit`: Character limit of the instance chat messages. * `remote_limit`: Hard character limit beyond which remote posts will be dropped. * `upload_limit`: File size limit of uploads (except for avatar, background, banner). @@ -40,7 +40,6 @@ To add configuration to your config file, you can copy it from the base config. * `allow_relay`: Enable Pleroma’s Relay, which makes it possible to follow a whole instance. * `public`: Makes the client API in authenticated mode-only except for user-profiles. Useful for disabling the Local Timeline and The Whole Known Network. Note that there is a dependent setting restricting or allowing unauthenticated access to specific resources, see `restrict_unauthenticated` for more details. * `quarantined_instances`: List of ActivityPub instances where private (DMs, followers-only) activities will not be send. -* `managed_config`: Whenether the config for pleroma-fe is configured in [:frontend_configurations](#frontend_configurations) or in ``static/config.json``. * `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML). * `extended_nickname_format`: Set to `true` to use extended local nicknames format (allows underscores/dashes). This will break federation with older software for theses nicknames. @@ -115,6 +114,7 @@ To add configuration to your config file, you can copy it from the base config. * `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)). * `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)). * `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.ActivityExpiration` to be enabled for processing the scheduled delections. + * `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines. * `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo). * `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value. @@ -225,6 +225,16 @@ Enables the worker which processes posts scheduled for deletion. Pinned posts ar * `enabled`: whether expired activities will be sent to the job queue to be deleted +## FedSockets +FedSockets is an experimental feature allowing for Pleroma backends to federate using a persistant websocket connection as opposed to making each federation a seperate http connection. This feature is currently off by default. It is configurable throught he following options. + +### :fedsockets +* `enabled`: Enables FedSockets for this instance. `false` by default. +* `connection_duration`: Time an idle websocket is kept open. +* `rejection_duration`: Failures to connect via FedSockets will not be retried for this period of time. +* `fed_socket_fetches` and `fed_socket_rejections`: Settings passed to `cachex` for the fetch registry, and rejection stacks. See `Pleroma.Web.FedSockets` for more details. + + ## Frontends ### :frontend_configurations @@ -314,6 +324,14 @@ This section describe PWA manifest instance-specific values. Currently this opti * `enabled`: Enables purge cache * `provider`: Which one of the [purge cache strategy](#purge-cache-strategy) to use. +## :media_preview_proxy + +* `enabled`: Enables proxying of remote media preview to the instance’s proxy. Requires enabled media proxy (`media_proxy/enabled`). +* `thumbnail_max_width`: Max width of preview thumbnail for images (video preview always has original dimensions). +* `thumbnail_max_height`: Max height of preview thumbnail for images (video preview always has original dimensions). +* `image_quality`: Quality of the output. Ranges from 0 (min quality) to 100 (max quality). +* `min_content_length`: Min content length to perform preview, in bytes. If greater than 0, media smaller in size will be served as is, without thumbnailing. + ### Purge cache strategy #### Pleroma.Web.MediaProxy.Invalidation.Script @@ -496,7 +514,7 @@ Settings for HTTP connection pool. * `:connection_acquisition_wait` - Timeout to acquire a connection from pool.The total max time is this value multiplied by the number of retries. * `connection_acquisition_retries` - Number of attempts to acquire the connection from the pool if it is overloaded. Each attempt is timed `:connection_acquisition_wait` apart. * `:max_connections` - Maximum number of connections in the pool. -* `:await_up_timeout` - Timeout to connect to the host. +* `:connect_timeout` - Timeout to connect to the host. * `:reclaim_multiplier` - Multiplied by `:max_connections` this will be the maximum number of idle connections that will be reclaimed in case the pool is overloaded. ### :pools @@ -515,7 +533,7 @@ There are four pools used: For each pool, the options are: * `:size` - limit to how much requests can be concurrently executed. -* `:timeout` - timeout while `gun` will wait for response +* `:recv_timeout` - timeout while `gun` will wait for response * `:max_waiting` - limit to how much requests can be waiting for others to finish, after this is reached, subsequent requests will be dropped. ## Captcha @@ -690,9 +708,8 @@ Pleroma has the following queues: Pleroma has these periodic job workers: -`Pleroma.Workers.Cron.ClearOauthTokenWorker` - a job worker to cleanup expired oauth tokens. - -Example: +* `Pleroma.Workers.Cron.DigestEmailsWorker` - digest emails for users with new mentions and follows +* `Pleroma.Workers.Cron.NewUsersDigestWorker` - digest emails for admins with new registrations ```elixir config :pleroma, Oban, @@ -704,7 +721,8 @@ config :pleroma, Oban, federator_outgoing: 50 ], crontab: [ - {"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker} + {"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker}, + {"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker} ] ``` @@ -971,7 +989,7 @@ Configure OAuth 2 provider capabilities: * `token_expires_in` - The lifetime in seconds of the access token. * `issue_new_refresh_token` - Keeps old refresh token or generate new refresh token when to obtain an access token. -* `clean_expired_tokens` - Enable a background job to clean expired oauth tokens. Defaults to `false`. Interval settings sets in configuration periodic jobs [`Oban.Cron`](#obancron) +* `clean_expired_tokens` - Enable a background job to clean expired oauth tokens. Defaults to `false`. ## Link parsing @@ -1090,3 +1108,10 @@ config :pleroma, :frontends, ``` This would serve the frontend from the the folder at `$instance_static/frontends/pleroma/stable`. You have to copy the frontend into this folder yourself. You can choose the name and ref any way you like, but they will be used by mix tasks to automate installation in the future, the name referring to the project and the ref referring to a commit. + +## Ephemeral activities (Pleroma.Workers.PurgeExpiredActivity) + +Settings to enable and configure expiration for ephemeral activities + +* `:enabled` - enables ephemeral activities creation +* `:min_lifetime` - minimum lifetime for ephemeral activities (in seconds). Default: 10 minutes. diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx @@ -9,6 +9,12 @@ proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off; +# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only +# and `localhost.` resolves to [::0] on some systems: see issue #930 +upstream phoenix { + server 127.0.0.1:4000 max_fails=5 fail_timeout=60s; +} + server { server_name example.tld; @@ -63,19 +69,16 @@ server { # the nginx default is 1m, not enough for large media uploads client_max_body_size 16m; + ignore_invalid_headers off; - location / { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $http_host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - # this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only - # and `localhost.` resolves to [::0] on some systems: see issue #930 - proxy_pass http://127.0.0.1:4000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - client_max_body_size 16m; + location / { + proxy_pass http://phoenix; } location ~ ^/(media|proxy) { @@ -83,12 +86,16 @@ server { slice 1m; proxy_cache_key $host$uri$is_args$args$slice_range; proxy_set_header Range $slice_range; - proxy_http_version 1.1; proxy_cache_valid 200 206 301 304 1h; proxy_cache_lock on; proxy_ignore_client_abort on; proxy_buffering on; chunked_transfer_encoding on; - proxy_pass http://127.0.0.1:4000; + proxy_pass http://phoenix; + } + + location /api/fedsocket/v1 { + proxy_request_buffering off; + proxy_pass http://phoenix/api/fedsocket/v1; } } diff --git a/lib/mix/pleroma.ex b/lib/mix/pleroma.ex @@ -18,6 +18,7 @@ defmodule Mix.Pleroma do @doc "Common functions to be reused in mix tasks" def start_pleroma do Pleroma.Config.Holder.save_default() + Pleroma.Config.Oban.warn() Application.put_env(:phoenix, :serve_endpoints, false, persistent: true) if Pleroma.Config.get(:env) != :test do diff --git a/lib/mix/tasks/pleroma/benchmark.ex b/lib/mix/tasks/pleroma/benchmark.ex @@ -91,20 +91,17 @@ defmodule Mix.Tasks.Pleroma.Benchmark do "Without conn and without pool" => fn -> {:ok, %Tesla.Env{}} = Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [], - adapter: [pool: :no_pool, receive_conn: false] + pool: :no_pool, + receive_conn: false ) end, "Without conn and with pool" => fn -> {:ok, %Tesla.Env{}} = - Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [], - adapter: [receive_conn: false] - ) + Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [], receive_conn: false) end, "With reused conn and without pool" => fn -> {:ok, %Tesla.Env{}} = - Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [], - adapter: [pool: :no_pool] - ) + Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [], pool: :no_pool) end, "With reused conn and with pool" => fn -> {:ok, %Tesla.Env{}} = Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500") diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex @@ -32,7 +32,8 @@ defmodule Mix.Tasks.Pleroma.Config do @spec migrate_to_db(Path.t() | nil) :: any() def migrate_to_db(file_path \\ nil) do - if Pleroma.Config.get([:configurable_from_database]) do + with true <- Pleroma.Config.get([:configurable_from_database]), + :ok <- Pleroma.Config.DeprecationWarnings.warn() do config_file = if file_path do file_path @@ -46,7 +47,8 @@ defmodule Mix.Tasks.Pleroma.Config do do_migrate_to_db(config_file) else - migration_error() + :error -> deprecation_error() + _ -> migration_error() end end @@ -120,6 +122,10 @@ defmodule Mix.Tasks.Pleroma.Config do ) end + defp deprecation_error do + shell_error("Migration is not allowed until all deprecation warnings have been resolved.") + end + if Code.ensure_loaded?(Config.Reader) do defp config_header, do: "import Config\r\n\r\n" defp read_file(config_file), do: Config.Reader.read_imports!(config_file) diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex @@ -99,7 +99,7 @@ defmodule Mix.Tasks.Pleroma.Database do where: fragment("(?)->>'likes' is not null", object.data), select: %{id: object.id, likes: fragment("(?)->>'likes'", object.data)} ) - |> Pleroma.RepoStreamer.chunk_stream(100) + |> Pleroma.Repo.chunk_stream(100, :batches) |> Stream.each(fn objects -> ids = objects @@ -133,8 +133,7 @@ defmodule Mix.Tasks.Pleroma.Database do days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365) Pleroma.Activity - |> join(:left, [a], u in assoc(a, :expiration)) - |> join(:inner, [a, _u], o in Object, + |> join(:inner, [a], o in Object, on: fragment( "(?->>'id') = COALESCE((?)->'object'->> 'id', (?)->>'object')", @@ -144,14 +143,20 @@ defmodule Mix.Tasks.Pleroma.Database do ) ) |> where(local: true) - |> where([a, u], is_nil(u)) |> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data)) - |> where([_a, _u, o], fragment("?->>'type' = 'Note'", o.data)) - |> Pleroma.RepoStreamer.chunk_stream(100) + |> where([_a, o], fragment("?->>'type' = 'Note'", o.data)) + |> Pleroma.Repo.chunk_stream(100, :batches) |> Stream.each(fn activities -> Enum.each(activities, fn activity -> - expires_at = Timex.shift(activity.inserted_at, days: days) - Pleroma.ActivityExpiration.create(activity, expires_at, false) + expires_at = + activity.inserted_at + |> DateTime.from_naive!("Etc/UTC") + |> Timex.shift(days: days) + + Pleroma.Workers.PurgeExpiredActivity.enqueue(%{ + activity_id: activity.id, + expires_at: expires_at + }) end) end) |> Stream.run() diff --git a/lib/mix/tasks/pleroma/emoji.ex b/lib/mix/tasks/pleroma/emoji.ex @@ -183,7 +183,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do IO.puts("Downloading the pack and generating SHA256") - binary_archive = Tesla.get!(client(), src).body + {:ok, %{body: binary_archive}} = Pleroma.HTTP.get(src) archive_sha = :crypto.hash(:sha256, binary_archive) |> Base.encode16() IO.puts("SHA256 is #{archive_sha}") @@ -252,7 +252,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do end defp fetch("http" <> _ = from) do - with {:ok, %{body: body}} <- Tesla.get(client(), from) do + with {:ok, %{body: body}} <- Pleroma.HTTP.get(from) do {:ok, body} end end @@ -271,13 +271,5 @@ defmodule Mix.Tasks.Pleroma.Emoji do ) end - defp client do - middleware = [ - {Tesla.Middleware.FollowRedirects, [max_redirects: 3]} - ] - - Tesla.client(middleware) - end - defp default_manifest, do: Pleroma.Config.get!([:emoji, :default_manifest]) end diff --git a/lib/mix/tasks/pleroma/frontend.ex b/lib/mix/tasks/pleroma/frontend.ex @@ -69,7 +69,7 @@ defmodule Mix.Tasks.Pleroma.Frontend do fe_label = "#{frontend} (#{ref})" - tmp_dir = Path.join(dest, "tmp") + tmp_dir = Path.join([instance_static_dir, "frontends", "tmp"]) with {_, :ok} <- {:download_or_unzip, download_or_unzip(frontend_info, tmp_dir, options[:file])}, @@ -124,9 +124,7 @@ defmodule Mix.Tasks.Pleroma.Frontend do url = String.replace(frontend_info["build_url"], "${ref}", frontend_info["ref"]) with {:ok, %{status: 200, body: zip_body}} <- - Pleroma.HTTP.get(url, [], - adapter: [pool: :media, timeout: 120_000, recv_timeout: 120_000] - ) do + Pleroma.HTTP.get(url, [], pool: :media, recv_timeout: 120_000) do unzip(zip_body, dest) else e -> {:error, e} @@ -135,6 +133,7 @@ defmodule Mix.Tasks.Pleroma.Frontend do defp install_frontend(frontend_info, source, dest) do from = frontend_info["build_dir"] || "dist" + File.rm_rf!(dest) File.mkdir_p!(dest) File.cp_r!(Path.join([source, from]), dest) :ok diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex @@ -179,7 +179,7 @@ defmodule Mix.Tasks.Pleroma.User do start_pleroma() Pleroma.User.Query.build(%{nickname: "@#{instance}"}) - |> Pleroma.RepoStreamer.chunk_stream(500) + |> Pleroma.Repo.chunk_stream(500, :batches) |> Stream.each(fn users -> users |> Enum.each(fn user -> @@ -370,7 +370,7 @@ defmodule Mix.Tasks.Pleroma.User do start_pleroma() Pleroma.User.Query.build(%{local: true}) - |> Pleroma.RepoStreamer.chunk_stream(500) + |> Pleroma.Repo.chunk_stream(500, :batches) |> Stream.each(fn users -> users |> Enum.each(fn user -> diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex @@ -7,7 +7,6 @@ defmodule Pleroma.Activity do alias Pleroma.Activity alias Pleroma.Activity.Queries - alias Pleroma.ActivityExpiration alias Pleroma.Bookmark alias Pleroma.Notification alias Pleroma.Object @@ -60,8 +59,6 @@ defmodule Pleroma.Activity do # typical case. has_one(:object, Object, on_delete: :nothing, foreign_key: :id) - has_one(:expiration, ActivityExpiration, on_delete: :delete_all) - timestamps() end @@ -304,14 +301,14 @@ defmodule Pleroma.Activity do |> Repo.all() end - def follow_requests_for_actor(%Pleroma.User{ap_id: ap_id}) do + def follow_requests_for_actor(%User{ap_id: ap_id}) do ap_id |> Queries.by_object_id() |> Queries.by_type("Follow") |> where([a], fragment("? ->> 'state' = 'pending'", a.data)) end - def following_requests_for_actor(%Pleroma.User{ap_id: ap_id}) do + def following_requests_for_actor(%User{ap_id: ap_id}) do Queries.by_type("Follow") |> where([a], fragment("?->>'state' = 'pending'", a.data)) |> where([a], a.actor == ^ap_id) diff --git a/lib/pleroma/activity_expiration.ex b/lib/pleroma/activity_expiration.ex @@ -1,74 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.ActivityExpiration do - use Ecto.Schema - - alias Pleroma.Activity - alias Pleroma.ActivityExpiration - alias Pleroma.Repo - - import Ecto.Changeset - import Ecto.Query - - @type t :: %__MODULE__{} - @min_activity_lifetime :timer.hours(1) - - schema "activity_expirations" do - belongs_to(:activity, Activity, type: FlakeId.Ecto.CompatType) - field(:scheduled_at, :naive_datetime) - end - - def changeset(%ActivityExpiration{} = expiration, attrs, validate_scheduled_at) do - expiration - |> cast(attrs, [:scheduled_at]) - |> validate_required([:scheduled_at]) - |> validate_scheduled_at(validate_scheduled_at) - end - - def get_by_activity_id(activity_id) do - ActivityExpiration - |> where([exp], exp.activity_id == ^activity_id) - |> Repo.one() - end - - def create(%Activity{} = activity, scheduled_at, validate_scheduled_at \\ true) do - %ActivityExpiration{activity_id: activity.id} - |> changeset(%{scheduled_at: scheduled_at}, validate_scheduled_at) - |> Repo.insert() - end - - def due_expirations(offset \\ 0) do - naive_datetime = - NaiveDateTime.utc_now() - |> NaiveDateTime.add(offset, :millisecond) - - ActivityExpiration - |> where([exp], exp.scheduled_at < ^naive_datetime) - |> limit(50) - |> preload(:activity) - |> Repo.all() - |> Enum.reject(fn %{activity: activity} -> - Activity.pinned_by_actor?(activity) - end) - end - - def validate_scheduled_at(changeset, false), do: changeset - - def validate_scheduled_at(changeset, true) do - validate_change(changeset, :scheduled_at, fn _, scheduled_at -> - if not expires_late_enough?(scheduled_at) do - [scheduled_at: "an ephemeral activity must live for at least one hour"] - else - [] - end - end) - end - - def expires_late_enough?(scheduled_at) do - now = NaiveDateTime.utc_now() - diff = NaiveDateTime.diff(scheduled_at, now, :millisecond) - diff > @min_activity_lifetime - end -end diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex @@ -22,13 +22,18 @@ defmodule Pleroma.Application do def repository, do: @repository def user_agent do - case Config.get([:http, :user_agent], :default) do - :default -> - info = "#{Pleroma.Web.base_url()} <#{Config.get([:instance, :email], "")}>" - named_version() <> "; " <> info - - custom -> - custom + if Process.whereis(Pleroma.Web.Endpoint) do + case Config.get([:http, :user_agent], :default) do + :default -> + info = "#{Pleroma.Web.base_url()} <#{Config.get([:instance, :email], "")}>" + named_version() <> "; " <> info + + custom -> + custom + end + else + # fallback, if endpoint is not started yet + "Pleroma Data Loader" end end @@ -39,9 +44,13 @@ defmodule Pleroma.Application do # every time the application is restarted, so we disable module # conflicts at runtime Code.compiler_options(ignore_module_conflict: true) + # Disable warnings_as_errors at runtime, it breaks Phoenix live reload + # due to protocol consolidation warnings + Code.compiler_options(warnings_as_errors: false) Pleroma.Telemetry.Logger.attach() Config.Holder.save_default() Pleroma.HTML.compile_scrubbers() + Pleroma.Config.Oban.warn() Config.DeprecationWarnings.warn() Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled() Pleroma.ApplicationRequirements.verify!() @@ -90,7 +99,7 @@ defmodule Pleroma.Application do {Oban, Config.get(Oban)} ] ++ task_children(@env) ++ - streamer_child(@env) ++ + dont_run_in_test(@env) ++ chat_child(@env, chat_enabled?()) ++ [ Pleroma.Web.Endpoint, @@ -179,16 +188,17 @@ defmodule Pleroma.Application do defp chat_enabled?, do: Config.get([:chat, :enabled]) - defp streamer_child(env) when env in [:test, :benchmark], do: [] + defp dont_run_in_test(env) when env in [:test, :benchmark], do: [] - defp streamer_child(_) do + defp dont_run_in_test(_) do [ {Registry, [ name: Pleroma.Web.Streamer.registry(), keys: :duplicate, partitions: System.schedulers_online() - ]} + ]}, + Pleroma.Web.FedSockets.Supervisor ] end diff --git a/lib/pleroma/chat.ex b/lib/pleroma/chat.ex @@ -6,7 +6,9 @@ defmodule Pleroma.Chat do use Ecto.Schema import Ecto.Changeset + import Ecto.Query + alias Pleroma.Chat alias Pleroma.Repo alias Pleroma.User @@ -69,4 +71,12 @@ defmodule Pleroma.Chat do conflict_target: [:user_id, :recipient] ) end + + @spec for_user_query(FlakeId.Ecto.CompatType.t()) :: Ecto.Query.t() + def for_user_query(user_id) do + from(c in Chat, + where: c.user_id == ^user_id, + order_by: [desc: c.updated_at] + ) + end end diff --git a/lib/pleroma/config/deprecation_warnings.ex b/lib/pleroma/config/deprecation_warnings.ex @@ -8,7 +8,7 @@ defmodule Pleroma.Config.DeprecationWarnings do require Logger alias Pleroma.Config - @type config_namespace() :: [atom()] + @type config_namespace() :: atom() | [atom()] @type config_map() :: {config_namespace(), config_namespace(), String.t()} @mrf_config_map [ @@ -26,6 +26,10 @@ defmodule Pleroma.Config.DeprecationWarnings do !!!DEPRECATION WARNING!!! You are using the old configuration mechanism for the hellthread filter. Please check config.md. """) + + :error + else + :ok end end @@ -47,15 +51,26 @@ defmodule Pleroma.Config.DeprecationWarnings do config :pleroma, :mrf_user_allowlist, #{inspect(rewritten, pretty: true)} """) + + :error + else + :ok end end def warn do - check_hellthread_threshold() - mrf_user_allowlist() - check_old_mrf_config() - check_media_proxy_whitelist_config() - check_welcome_message_config() + with :ok <- check_hellthread_threshold(), + :ok <- mrf_user_allowlist(), + :ok <- check_old_mrf_config(), + :ok <- check_media_proxy_whitelist_config(), + :ok <- check_welcome_message_config(), + :ok <- check_gun_pool_options(), + :ok <- check_activity_expiration_config() do + :ok + else + _ -> + :error + end end def check_welcome_message_config do @@ -72,6 +87,10 @@ defmodule Pleroma.Config.DeprecationWarnings do \n* `config :pleroma, :instance, welcome_user_nickname` is now `config :pleroma, :welcome, :direct_message, :sender_nickname` \n* `config :pleroma, :instance, welcome_message` is now `config :pleroma, :welcome, :direct_message, :message` """) + + :error + else + :ok end end @@ -99,8 +118,11 @@ defmodule Pleroma.Config.DeprecationWarnings do end end) - if warning != "" do + if warning == "" do + :ok + else Logger.warn(warning_preface <> warning) + :error end end @@ -113,6 +135,71 @@ defmodule Pleroma.Config.DeprecationWarnings do !!!DEPRECATION WARNING!!! Your config is using old format (only domain) for MediaProxy whitelist option. Setting should work for now, but you are advised to change format to scheme with port to prevent possible issues later. """) + + :error + else + :ok + end + end + + def check_gun_pool_options do + pool_config = Config.get(:connections_pool) + + if timeout = pool_config[:await_up_timeout] do + Logger.warn(""" + !!!DEPRECATION WARNING!!! + Your config is using old setting name `await_up_timeout` instead of `connect_timeout`. Setting should work for now, but you are advised to change format to scheme with port to prevent possible issues later. + """) + + Config.put(:connections_pool, Keyword.put_new(pool_config, :connect_timeout, timeout)) end + + pools_configs = Config.get(:pools) + + warning_preface = """ + !!!DEPRECATION WARNING!!! + Your config is using old setting name `timeout` instead of `recv_timeout` in pool settings. Setting should work for now, but you are advised to change format to scheme with port to prevent possible issues later. + """ + + updated_config = + Enum.reduce(pools_configs, [], fn {pool_name, config}, acc -> + if timeout = config[:timeout] do + Keyword.put(acc, pool_name, Keyword.put_new(config, :recv_timeout, timeout)) + else + acc + end + end) + + if updated_config != [] do + pool_warnings = + updated_config + |> Keyword.keys() + |> Enum.map(fn pool_name -> + "\n* `:timeout` options in #{pool_name} pool is now `:recv_timeout`" + end) + + Logger.warn(Enum.join([warning_preface | pool_warnings])) + + Config.put(:pools, updated_config) + :error + else + :ok + end + end + + @spec check_activity_expiration_config() :: :ok | nil + def check_activity_expiration_config do + warning_preface = """ + !!!DEPRECATION WARNING!!! + Your config is using old namespace for activity expiration configuration. Setting should work for now, but you are advised to change to new namespace to prevent possible issues later: + """ + + move_namespace_and_warn( + [ + {Pleroma.ActivityExpiration, Pleroma.Workers.PurgeExpiredActivity, + "\n* `config :pleroma, Pleroma.ActivityExpiration` is now `config :pleroma, Pleroma.Workers.PurgeExpiredActivity`"} + ], + warning_preface + ) end end diff --git a/lib/pleroma/config/oban.ex b/lib/pleroma/config/oban.ex @@ -0,0 +1,34 @@ +defmodule Pleroma.Config.Oban do + require Logger + + def warn do + oban_config = Pleroma.Config.get(Oban) + + crontab = + [ + Pleroma.Workers.Cron.StatsWorker, + Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker, + Pleroma.Workers.Cron.ClearOauthTokenWorker + ] + |> Enum.reduce(oban_config[:crontab], fn removed_worker, acc -> + with acc when is_list(acc) <- acc, + setting when is_tuple(setting) <- + Enum.find(acc, fn {_, worker} -> worker == removed_worker end) do + """ + !!!OBAN CONFIG WARNING!!! + You are using old workers in Oban crontab settings, which were removed. + Please, remove setting from crontab in your config file (prod.secret.exs): #{ + inspect(setting) + } + """ + |> Logger.warn() + + List.delete(acc, setting) + else + _ -> acc + end + end) + + Pleroma.Config.put(Oban, Keyword.put(oban_config, :crontab, crontab)) + end +end diff --git a/lib/pleroma/ecto_type/activity_pub/object_validators/emoji.ex b/lib/pleroma/ecto_type/activity_pub/object_validators/emoji.ex @@ -0,0 +1,34 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.Emoji do + use Ecto.Type + + def type, do: :map + + def cast(data) when is_map(data) do + has_invalid_emoji? = + Enum.find(data, fn + {name, uri} when is_binary(name) and is_binary(uri) -> + # based on ObjectValidators.Uri.cast() + case URI.parse(uri) do + %URI{host: nil} -> true + %URI{host: ""} -> true + %URI{scheme: scheme} when scheme in ["https", "http"] -> false + _ -> true + end + + {_name, _uri} -> + true + end) + + if has_invalid_emoji?, do: :error, else: {:ok, data} + end + + def cast(_data), do: :error + + def dump(data), do: {:ok, data} + + def load(data), do: {:ok, data} +end diff --git a/lib/pleroma/gun/conn.ex b/lib/pleroma/gun/conn.ex @@ -13,7 +13,7 @@ defmodule Pleroma.Gun.Conn do opts = opts |> Enum.into(%{}) - |> Map.put_new(:await_up_timeout, pool_opts[:await_up_timeout] || 5_000) + |> Map.put_new(:connect_timeout, pool_opts[:connect_timeout] || 5_000) |> Map.put_new(:supervise, false) |> maybe_add_tls_opts(uri) @@ -50,10 +50,10 @@ defmodule Pleroma.Gun.Conn do with open_opts <- Map.delete(opts, :tls_opts), {:ok, conn} <- Gun.open(proxy_host, proxy_port, open_opts), - {:ok, _} <- Gun.await_up(conn, opts[:await_up_timeout]), + {:ok, protocol} <- Gun.await_up(conn, opts[:connect_timeout]), stream <- Gun.connect(conn, connect_opts), {:response, :fin, 200, _} <- Gun.await(conn, stream) do - {:ok, conn} + {:ok, conn, protocol} else error -> Logger.warn( @@ -88,8 +88,8 @@ defmodule Pleroma.Gun.Conn do |> Map.put(:socks_opts, socks_opts) with {:ok, conn} <- Gun.open(proxy_host, proxy_port, opts), - {:ok, _} <- Gun.await_up(conn, opts[:await_up_timeout]) do - {:ok, conn} + {:ok, protocol} <- Gun.await_up(conn, opts[:connect_timeout]) do + {:ok, conn, protocol} else error -> Logger.warn( @@ -106,8 +106,8 @@ defmodule Pleroma.Gun.Conn do host = Pleroma.HTTP.AdapterHelper.parse_host(host) with {:ok, conn} <- Gun.open(host, port, opts), - {:ok, _} <- Gun.await_up(conn, opts[:await_up_timeout]) do - {:ok, conn} + {:ok, protocol} <- Gun.await_up(conn, opts[:connect_timeout]) do + {:ok, conn, protocol} else error -> Logger.warn( diff --git a/lib/pleroma/gun/connection_pool/worker.ex b/lib/pleroma/gun/connection_pool/worker.ex @@ -15,7 +15,7 @@ defmodule Pleroma.Gun.ConnectionPool.Worker do @impl true def handle_continue({:connect, [key, uri, opts, client_pid]}, _) do - with {:ok, conn_pid} <- Gun.Conn.open(uri, opts), + with {:ok, conn_pid, protocol} <- Gun.Conn.open(uri, opts), Process.link(conn_pid) do time = :erlang.monotonic_time(:millisecond) @@ -27,8 +27,12 @@ defmodule Pleroma.Gun.ConnectionPool.Worker do send(client_pid, {:conn_pid, conn_pid}) {:noreply, - %{key: key, timer: nil, client_monitors: %{client_pid => Process.monitor(client_pid)}}, - :hibernate} + %{ + key: key, + timer: nil, + client_monitors: %{client_pid => Process.monitor(client_pid)}, + protocol: protocol + }, :hibernate} else err -> {:stop, {:shutdown, err}, nil} @@ -53,14 +57,20 @@ defmodule Pleroma.Gun.ConnectionPool.Worker do end @impl true - def handle_call(:add_client, {client_pid, _}, %{key: key} = state) do + def handle_call(:add_client, {client_pid, _}, %{key: key, protocol: protocol} = state) do time = :erlang.monotonic_time(:millisecond) - {{conn_pid, _, _, _}, _} = + {{conn_pid, used_by, _, _}, _} = Registry.update_value(@registry, key, fn {conn_pid, used_by, crf, last_reference} -> {conn_pid, [client_pid | used_by], crf(time - last_reference, crf), time} end) + :telemetry.execute( + [:pleroma, :connection_pool, :client, :add], + %{client_pid: client_pid, clients: used_by}, + %{key: state.key, protocol: protocol} + ) + state = if state.timer != nil do Process.cancel_timer(state[:timer]) @@ -83,25 +93,18 @@ defmodule Pleroma.Gun.ConnectionPool.Worker do end) {ref, state} = pop_in(state.client_monitors[client_pid]) - # DOWN message can receive right after `remove_client` call and cause worker to terminate - state = - if is_nil(ref) do - state - else - Process.demonitor(ref) - timer = - if used_by == [] do - max_idle = Pleroma.Config.get([:connections_pool, :max_idle_time], 30_000) - Process.send_after(self(), :idle_close, max_idle) - else - nil - end + Process.demonitor(ref, [:flush]) - %{state | timer: timer} + timer = + if used_by == [] do + max_idle = Pleroma.Config.get([:connections_pool, :max_idle_time], 30_000) + Process.send_after(self(), :idle_close, max_idle) + else + nil end - {:reply, :ok, state, :hibernate} + {:reply, :ok, %{state | timer: timer}, :hibernate} end @impl true @@ -131,7 +134,7 @@ defmodule Pleroma.Gun.ConnectionPool.Worker do @impl true def handle_info({:DOWN, _ref, :process, pid, reason}, state) do :telemetry.execute( - [:pleroma, :connection_pool, :client_death], + [:pleroma, :connection_pool, :client, :dead], %{client_pid: pid, reason: reason}, %{key: state.key} ) diff --git a/lib/pleroma/helpers/media_helper.ex b/lib/pleroma/helpers/media_helper.ex @@ -0,0 +1,150 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Helpers.MediaHelper do + @moduledoc """ + Handles common media-related operations. + """ + + alias Pleroma.HTTP + + def image_resize(url, options) do + with executable when is_binary(executable) <- System.find_executable("convert"), + {:ok, args} <- prepare_image_resize_args(options), + {:ok, env} <- HTTP.get(url, [], pool: :media), + {:ok, fifo_path} <- mkfifo() do + args = List.flatten([fifo_path, args]) + run_fifo(fifo_path, env, executable, args) + else + nil -> {:error, {:convert, :command_not_found}} + {:error, _} = error -> error + end + end + + defp prepare_image_resize_args( + %{max_width: max_width, max_height: max_height, format: "png"} = options + ) do + quality = options[:quality] || 85 + resize = Enum.join([max_width, "x", max_height, ">"]) + + args = [ + "-resize", + resize, + "-quality", + to_string(quality), + "png:-" + ] + + {:ok, args} + end + + defp prepare_image_resize_args(%{max_width: max_width, max_height: max_height} = options) do + quality = options[:quality] || 85 + resize = Enum.join([max_width, "x", max_height, ">"]) + + args = [ + "-interlace", + "Plane", + "-resize", + resize, + "-quality", + to_string(quality), + "jpg:-" + ] + + {:ok, args} + end + + defp prepare_image_resize_args(_), do: {:error, :missing_options} + + # Note: video thumbnail is intentionally not resized (always has original dimensions) + def video_framegrab(url) do + with executable when is_binary(executable) <- System.find_executable("ffmpeg"), + {:ok, env} <- HTTP.get(url, [], pool: :media), + {:ok, fifo_path} <- mkfifo(), + args = [ + "-y", + "-i", + fifo_path, + "-vframes", + "1", + "-f", + "mjpeg", + "-loglevel", + "error", + "-" + ] do + run_fifo(fifo_path, env, executable, args) + else + nil -> {:error, {:ffmpeg, :command_not_found}} + {:error, _} = error -> error + end + end + + defp run_fifo(fifo_path, env, executable, args) do + pid = + Port.open({:spawn_executable, executable}, [ + :use_stdio, + :stream, + :exit_status, + :binary, + args: args + ]) + + fifo = Port.open(to_charlist(fifo_path), [:eof, :binary, :stream, :out]) + fix = Pleroma.Helpers.QtFastStart.fix(env.body) + true = Port.command(fifo, fix) + :erlang.port_close(fifo) + loop_recv(pid) + after + File.rm(fifo_path) + end + + defp mkfifo do + path = Path.join(System.tmp_dir!(), "pleroma-media-preview-pipe-#{Ecto.UUID.generate()}") + + case System.cmd("mkfifo", [path]) do + {_, 0} -> + spawn(fifo_guard(path)) + {:ok, path} + + {_, err} -> + {:error, {:fifo_failed, err}} + end + end + + defp fifo_guard(path) do + pid = self() + + fn -> + ref = Process.monitor(pid) + + receive do + {:DOWN, ^ref, :process, ^pid, _} -> + File.rm(path) + end + end + end + + defp loop_recv(pid) do + loop_recv(pid, <<>>) + end + + defp loop_recv(pid, acc) do + receive do + {^pid, {:data, data}} -> + loop_recv(pid, acc <> data) + + {^pid, {:exit_status, 0}} -> + {:ok, acc} + + {^pid, {:exit_status, status}} -> + {:error, status} + after + 5000 -> + :erlang.port_close(pid) + {:error, :timeout} + end + end +end diff --git a/lib/pleroma/helpers/qt_fast_start.ex b/lib/pleroma/helpers/qt_fast_start.ex @@ -0,0 +1,131 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Helpers.QtFastStart do + @moduledoc """ + (WIP) Converts a "slow start" (data before metadatas) mov/mp4 file to a "fast start" one (metadatas before data). + """ + + # TODO: Cleanup and optimizations + # Inspirations: https://www.ffmpeg.org/doxygen/3.4/qt-faststart_8c_source.html + # https://github.com/danielgtaylor/qtfaststart/blob/master/qtfaststart/processor.py + # ISO/IEC 14496-12:2015, ISO/IEC 15444-12:2015 + # Paracetamol + + def fix(<<0x00, 0x00, 0x00, _, 0x66, 0x74, 0x79, 0x70, _::bits>> = binary) do + index = fix(binary, 0, nil, nil, []) + + case index do + :abort -> binary + [{"ftyp", _, _, _, _}, {"mdat", _, _, _, _} | _] -> faststart(index) + [{"ftyp", _, _, _, _}, {"free", _, _, _, _}, {"mdat", _, _, _, _} | _] -> faststart(index) + _ -> binary + end + end + + def fix(binary) do + binary + end + + # MOOV have been seen before MDAT- abort + defp fix(<<_::bits>>, _, true, false, _) do + :abort + end + + defp fix( + <<size::integer-big-size(32), fourcc::bits-size(32), rest::bits>>, + pos, + got_moov, + got_mdat, + acc + ) do + full_size = (size - 8) * 8 + <<data::bits-size(full_size), rest::bits>> = rest + + acc = [ + {fourcc, pos, pos + size, size, + <<size::integer-big-size(32), fourcc::bits-size(32), data::bits>>} + | acc + ] + + fix(rest, pos + size, got_moov || fourcc == "moov", got_mdat || fourcc == "mdat", acc) + end + + defp fix(<<>>, _pos, _, _, acc) do + :lists.reverse(acc) + end + + defp faststart(index) do + {{_ftyp, _, _, _, ftyp}, index} = List.keytake(index, "ftyp", 0) + + # Skip re-writing the free fourcc as it's kind of useless. + # Why stream useless bytes when you can do without? + {free_size, index} = + case List.keytake(index, "free", 0) do + {{_, _, _, size, _}, index} -> {size, index} + _ -> {0, index} + end + + {{_moov, _, _, moov_size, moov}, index} = List.keytake(index, "moov", 0) + offset = -free_size + moov_size + rest = for {_, _, _, _, data} <- index, do: data, into: [] + <<moov_head::bits-size(64), moov_data::bits>> = moov + [ftyp, moov_head, fix_moov(moov_data, offset, []), rest] + end + + defp fix_moov( + <<size::integer-big-size(32), fourcc::bits-size(32), rest::bits>>, + offset, + acc + ) do + full_size = (size - 8) * 8 + <<data::bits-size(full_size), rest::bits>> = rest + + data = + cond do + fourcc in ["trak", "mdia", "minf", "stbl"] -> + # Theses contains sto or co64 part + [<<size::integer-big-size(32), fourcc::bits-size(32)>>, fix_moov(data, offset, [])] + + fourcc in ["stco", "co64"] -> + # fix the damn thing + <<version::integer-big-size(32), count::integer-big-size(32), rest::bits>> = data + + entry_size = + case fourcc do + "stco" -> 32 + "co64" -> 64 + end + + [ + <<size::integer-big-size(32), fourcc::bits-size(32), version::integer-big-size(32), + count::integer-big-size(32)>>, + rewrite_entries(entry_size, offset, rest, []) + ] + + true -> + [<<size::integer-big-size(32), fourcc::bits-size(32)>>, data] + end + + acc = [acc | data] + fix_moov(rest, offset, acc) + end + + defp fix_moov(<<>>, _, acc), do: acc + + for size <- [32, 64] do + defp rewrite_entries( + unquote(size), + offset, + <<pos::integer-big-size(unquote(size)), rest::bits>>, + acc + ) do + rewrite_entries(unquote(size), offset, rest, [ + acc | <<pos + offset::integer-big-size(unquote(size))>> + ]) + end + end + + defp rewrite_entries(_, _, <<>>, acc), do: acc +end diff --git a/lib/pleroma/helpers/uri_helper.ex b/lib/pleroma/helpers/uri_helper.ex @@ -3,18 +3,22 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Helpers.UriHelper do - def append_uri_params(uri, appended_params) do + def modify_uri_params(uri, overridden_params, deleted_params \\ []) do uri = URI.parse(uri) - appended_params = for {k, v} <- appended_params, into: %{}, do: {to_string(k), v} - existing_params = URI.query_decoder(uri.query || "") |> Enum.into(%{}) - updated_params_keys = Enum.uniq(Map.keys(existing_params) ++ Map.keys(appended_params)) + + existing_params = URI.query_decoder(uri.query || "") |> Map.new() + overridden_params = Map.new(overridden_params, fn {k, v} -> {to_string(k), v} end) + deleted_params = Enum.map(deleted_params, &to_string/1) updated_params = - for k <- updated_params_keys, do: {k, appended_params[k] || existing_params[k]} + existing_params + |> Map.merge(overridden_params) + |> Map.drop(deleted_params) uri |> Map.put(:query, URI.encode_query(updated_params)) |> URI.to_string() + |> String.replace_suffix("?", "") end def maybe_add_base("/" <> uri, base), do: Path.join([base, uri]) diff --git a/lib/pleroma/http/adapter_helper.ex b/lib/pleroma/http/adapter_helper.ex @@ -6,7 +6,7 @@ defmodule Pleroma.HTTP.AdapterHelper do @moduledoc """ Configure Tesla.Client with default and customized adapter options. """ - @defaults [pool: :federation] + @defaults [pool: :federation, connect_timeout: 5_000, recv_timeout: 5_000] @type proxy_type() :: :socks4 | :socks5 @type host() :: charlist() | :inet.ip_address() @@ -19,7 +19,6 @@ defmodule Pleroma.HTTP.AdapterHelper do | {Connection.proxy_type(), Connection.host(), pos_integer()} @callback options(keyword(), URI.t()) :: keyword() - @callback get_conn(URI.t(), keyword()) :: {:ok, term()} | {:error, term()} @spec format_proxy(String.t() | tuple() | nil) :: proxy() | nil def format_proxy(nil), do: nil @@ -47,9 +46,6 @@ defmodule Pleroma.HTTP.AdapterHelper do |> adapter_helper().options(uri) end - @spec get_conn(URI.t(), keyword()) :: {:ok, keyword()} | {:error, atom()} - def get_conn(uri, opts), do: adapter_helper().get_conn(uri, opts) - defp adapter, do: Application.get_env(:tesla, :adapter) defp adapter_helper do diff --git a/lib/pleroma/http/adapter_helper/gun.ex b/lib/pleroma/http/adapter_helper/gun.ex @@ -6,18 +6,13 @@ defmodule Pleroma.HTTP.AdapterHelper.Gun do @behaviour Pleroma.HTTP.AdapterHelper alias Pleroma.Config - alias Pleroma.Gun.ConnectionPool alias Pleroma.HTTP.AdapterHelper require Logger @defaults [ - connect_timeout: 5_000, - domain_lookup_timeout: 5_000, - tls_handshake_timeout: 5_000, retry: 1, - retry_timeout: 1000, - await_up_timeout: 5_000 + retry_timeout: 1_000 ] @type pool() :: :federation | :upload | :media | :default @@ -46,23 +41,17 @@ defmodule Pleroma.HTTP.AdapterHelper.Gun do end defp put_timeout(opts) do + {recv_timeout, opts} = Keyword.pop(opts, :recv_timeout, pool_timeout(opts[:pool])) # this is the timeout to receive a message from Gun - Keyword.put_new(opts, :timeout, pool_timeout(opts[:pool])) + # `:timeout` key is used in Tesla + Keyword.put(opts, :timeout, recv_timeout) end @spec pool_timeout(pool()) :: non_neg_integer() def pool_timeout(pool) do - default = Config.get([:pools, :default, :timeout], 5_000) + default = Config.get([:pools, :default, :recv_timeout], 5_000) - Config.get([:pools, pool, :timeout], default) - end - - @spec get_conn(URI.t(), keyword()) :: {:ok, keyword()} | {:error, atom()} - def get_conn(uri, opts) do - case ConnectionPool.get_conn(uri, opts) do - {:ok, conn_pid} -> {:ok, Keyword.merge(opts, conn: conn_pid, close_conn: false)} - err -> err - end + Config.get([:pools, pool, :recv_timeout], default) end @prefix Pleroma.Gun.ConnectionPool diff --git a/lib/pleroma/http/adapter_helper/hackney.ex b/lib/pleroma/http/adapter_helper/hackney.ex @@ -2,11 +2,8 @@ defmodule Pleroma.HTTP.AdapterHelper.Hackney do @behaviour Pleroma.HTTP.AdapterHelper @defaults [ - connect_timeout: 10_000, - recv_timeout: 20_000, follow_redirect: true, - force_redirect: true, - pool: :federation + force_redirect: true ] @spec options(keyword(), URI.t()) :: keyword() @@ -19,6 +16,7 @@ defmodule Pleroma.HTTP.AdapterHelper.Hackney do |> Keyword.merge(config_opts) |> Keyword.merge(connection_opts) |> add_scheme_opts(uri) + |> maybe_add_with_body() |> Pleroma.HTTP.AdapterHelper.maybe_add_proxy(proxy) end @@ -28,6 +26,11 @@ defmodule Pleroma.HTTP.AdapterHelper.Hackney do defp add_scheme_opts(opts, _), do: opts - @spec get_conn(URI.t(), keyword()) :: {:ok, keyword()} - def get_conn(_uri, opts), do: {:ok, opts} + defp maybe_add_with_body(opts) do + if opts[:max_body] do + Keyword.put(opts, :with_body, true) + else + opts + end + end end diff --git a/lib/pleroma/http/ex_aws.ex b/lib/pleroma/http/ex_aws.ex @@ -11,7 +11,7 @@ defmodule Pleroma.HTTP.ExAws do @impl true def request(method, url, body \\ "", headers \\ [], http_opts \\ []) do - http_opts = Keyword.put_new(http_opts, :adapter, pool: :upload) + http_opts = Keyword.put_new(http_opts, :pool, :upload) case HTTP.request(method, url, body, headers, http_opts) do {:ok, env} -> diff --git a/lib/pleroma/http/http.ex b/lib/pleroma/http/http.ex @@ -60,30 +60,23 @@ defmodule Pleroma.HTTP do {:ok, Env.t()} | {:error, any()} def request(method, url, body, headers, options) when is_binary(url) do uri = URI.parse(url) - adapter_opts = AdapterHelper.options(uri, options[:adapter] || []) - - case AdapterHelper.get_conn(uri, adapter_opts) do - {:ok, adapter_opts} -> - options = put_in(options[:adapter], adapter_opts) - params = options[:params] || [] - request = build_request(method, headers, options, url, body, params) - - adapter = Application.get_env(:tesla, :adapter) - - client = Tesla.client(adapter_middlewares(adapter), adapter) - - maybe_limit( - fn -> - request(client, request) - end, - adapter, - adapter_opts - ) - - # Connection release is handled in a custom FollowRedirects middleware - err -> - err - end + adapter_opts = AdapterHelper.options(uri, options || []) + + options = put_in(options[:adapter], adapter_opts) + params = options[:params] || [] + request = build_request(method, headers, options, url, body, params) + + adapter = Application.get_env(:tesla, :adapter) + + client = Tesla.client(adapter_middlewares(adapter), adapter) + + maybe_limit( + fn -> + request(client, request) + end, + adapter, + adapter_opts + ) end @spec request(Client.t(), keyword()) :: {:ok, Env.t()} | {:error, any()} @@ -110,7 +103,7 @@ defmodule Pleroma.HTTP do end defp adapter_middlewares(Tesla.Adapter.Gun) do - [Pleroma.HTTP.Middleware.FollowRedirects] + [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.ConnectionPool] end defp adapter_middlewares(_), do: [] diff --git a/lib/pleroma/http/tzdata.ex b/lib/pleroma/http/tzdata.ex @@ -11,7 +11,7 @@ defmodule Pleroma.HTTP.Tzdata do @impl true def get(url, headers, options) do - options = Keyword.put_new(options, :adapter, pool: :default) + options = Keyword.put_new(options, :pool, :default) with {:ok, %Tesla.Env{} = env} <- HTTP.get(url, headers, options) do {:ok, {env.status, env.headers, env.body}} @@ -20,7 +20,7 @@ defmodule Pleroma.HTTP.Tzdata do @impl true def head(url, headers, options) do - options = Keyword.put_new(options, :adapter, pool: :default) + options = Keyword.put_new(options, :pool, :default) with {:ok, %Tesla.Env{} = env} <- HTTP.head(url, headers, options) do {:ok, {env.status, env.headers}} diff --git a/lib/pleroma/instances/instance.ex b/lib/pleroma/instances/instance.ex @@ -156,16 +156,12 @@ defmodule Pleroma.Instances.Instance do defp scrape_favicon(%URI{} = instance_uri) do try do with {:ok, %Tesla.Env{body: html}} <- - Pleroma.HTTP.get(to_string(instance_uri), [{"accept", "text/html"}], - adapter: [pool: :media] - ), - favicon_rel <- - html - |> Floki.parse_document!() - |> Floki.attribute("link[rel=icon]", "href") - |> List.first(), - favicon <- URI.merge(instance_uri, favicon_rel) |> to_string(), - true <- is_binary(favicon) do + Pleroma.HTTP.get(to_string(instance_uri), [{"accept", "text/html"}], pool: :media), + {_, [favicon_rel | _]} when is_binary(favicon_rel) <- + {:parse, + html |> Floki.parse_document!() |> Floki.attribute("link[rel=icon]", "href")}, + {_, favicon} when is_binary(favicon) <- + {:merge, URI.merge(instance_uri, favicon_rel) |> to_string()} do favicon else _ -> nil diff --git a/lib/pleroma/mfa/token.ex b/lib/pleroma/mfa/token.ex @@ -10,10 +10,11 @@ defmodule Pleroma.MFA.Token do alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web.OAuth.Authorization - alias Pleroma.Web.OAuth.Token, as: OAuthToken @expires 300 + @type t() :: %__MODULE__{} + schema "mfa_tokens" do field(:token, :string) field(:valid_until, :naive_datetime_usec) @@ -24,6 +25,7 @@ defmodule Pleroma.MFA.Token do timestamps() end + @spec get_by_token(String.t()) :: {:ok, t()} | {:error, :not_found} def get_by_token(token) do from( t in __MODULE__, @@ -33,33 +35,40 @@ defmodule Pleroma.MFA.Token do |> Repo.find_resource() end - def validate(token) do - with {:fetch_token, {:ok, token}} <- {:fetch_token, get_by_token(token)}, - {:expired, false} <- {:expired, is_expired?(token)} do + @spec validate(String.t()) :: {:ok, t()} | {:error, :not_found} | {:error, :expired_token} + def validate(token_str) do + with {:ok, token} <- get_by_token(token_str), + false <- expired?(token) do {:ok, token} - else - {:expired, _} -> {:error, :expired_token} - {:fetch_token, _} -> {:error, :not_found} - error -> {:error, error} end end - def create_token(%User{} = user) do - %__MODULE__{} - |> change - |> assign_user(user) - |> put_token - |> put_valid_until - |> Repo.insert() + defp expired?(%__MODULE__{valid_until: valid_until}) do + with true <- NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) > 0 do + {:error, :expired_token} + end + end + + @spec create(User.t(), Authorization.t() | nil) :: {:ok, t()} | {:error, Ecto.Changeset.t()} + def create(user, authorization \\ nil) do + with {:ok, token} <- do_create(user, authorization) do + Pleroma.Workers.PurgeExpiredToken.enqueue(%{ + token_id: token.id, + valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"), + mod: __MODULE__ + }) + + {:ok, token} + end end - def create_token(user, authorization) do + defp do_create(user, authorization) do %__MODULE__{} - |> change + |> change() |> assign_user(user) - |> assign_authorization(authorization) - |> put_token - |> put_valid_until + |> maybe_assign_authorization(authorization) + |> put_token() + |> put_valid_until() |> Repo.insert() end @@ -69,15 +78,19 @@ defmodule Pleroma.MFA.Token do |> validate_required([:user]) end - defp assign_authorization(changeset, authorization) do + defp maybe_assign_authorization(changeset, %Authorization{} = authorization) do changeset |> put_assoc(:authorization, authorization) |> validate_required([:authorization]) end + defp maybe_assign_authorization(changeset, _), do: changeset + defp put_token(changeset) do + token = Pleroma.Web.OAuth.Token.Utils.generate_token() + changeset - |> change(%{token: OAuthToken.Utils.generate_token()}) + |> change(%{token: token}) |> validate_required([:token]) |> unique_constraint(:token) end @@ -89,18 +102,4 @@ defmodule Pleroma.MFA.Token do |> change(%{valid_until: expires_in}) |> validate_required([:valid_until]) end - - def is_expired?(%__MODULE__{valid_until: valid_until}) do - NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) > 0 - end - - def is_expired?(_), do: false - - def delete_expired_tokens do - from( - q in __MODULE__, - where: fragment("?", q.valid_until) < ^Timex.now() - ) - |> Repo.delete_all() - end end diff --git a/lib/pleroma/migration_helper/notification_backfill.ex b/lib/pleroma/migration_helper/notification_backfill.ex @@ -19,13 +19,13 @@ defmodule Pleroma.MigrationHelper.NotificationBackfill do query |> Repo.chunk_stream(100) |> Enum.each(fn notification -> - type = - notification.activity - |> type_from_activity() + if notification.activity do + type = type_from_activity(notification.activity) - notification - |> Ecto.Changeset.change(%{type: type}) - |> Repo.update() + notification + |> Ecto.Changeset.change(%{type: type}) + |> Repo.update() + end end) end @@ -72,8 +72,7 @@ defmodule Pleroma.MigrationHelper.NotificationBackfill do "pleroma:emoji_reaction" "Create" -> - activity - |> type_from_activity_object() + type_from_activity_object(activity) t -> raise "No notification type for activity type #{t}" diff --git a/lib/pleroma/moderation_log.ex b/lib/pleroma/moderation_log.ex @@ -320,6 +320,19 @@ defmodule Pleroma.ModerationLog do |> insert_log_entry_with_message() end + @spec insert_log(%{actor: User, action: String.t(), subject_id: String.t()}) :: + {:ok, ModerationLog} | {:error, any} + def insert_log(%{actor: %User{} = actor, action: "chat_message_delete", subject_id: subject_id}) do + %ModerationLog{ + data: %{ + "actor" => %{"nickname" => actor.nickname}, + "action" => "chat_message_delete", + "subject_id" => subject_id + } + } + |> insert_log_entry_with_message() + end + @spec insert_log_entry_with_message(ModerationLog) :: {:ok, ModerationLog} | {:error, any} defp insert_log_entry_with_message(entry) do entry.data["message"] @@ -627,6 +640,17 @@ defmodule Pleroma.ModerationLog do "@#{actor_nickname} updated users: #{users_to_nicknames_string(subjects)}" end + @spec get_log_entry_message(ModerationLog) :: String.t() + def get_log_entry_message(%ModerationLog{ + data: %{ + "actor" => %{"nickname" => actor_nickname}, + "action" => "chat_message_delete", + "subject_id" => subject_id + } + }) do + "@#{actor_nickname} deleted chat message ##{subject_id}" + end + defp nicknames_to_string(nicknames) do nicknames |> Enum.map(&"@#{&1}") diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex @@ -648,4 +648,16 @@ defmodule Pleroma.Notification do ) |> Repo.one() end + + @spec mark_context_as_read(User.t(), String.t()) :: {integer(), nil | [term()]} + def mark_context_as_read(%User{id: id}, context) do + from( + n in Notification, + join: a in assoc(n, :activity), + where: n.user_id == ^id, + where: n.seen == false, + where: fragment("?->>'context'", a.data) == ^context + ) + |> Repo.update_all(set: [seen: true]) + end end diff --git a/lib/pleroma/object/containment.ex b/lib/pleroma/object/containment.ex @@ -44,13 +44,6 @@ defmodule Pleroma.Object.Containment do nil end - # TODO: We explicitly allow 'tag' URIs through, due to references to legacy OStatus - # objects being present in the test suite environment. Once these objects are - # removed, please also remove this. - if Mix.env() == :test do - defp compare_uris(_, %URI{scheme: "tag"}), do: :ok - end - defp compare_uris(%URI{host: host} = _id_uri, %URI{host: host} = _other_uri), do: :ok defp compare_uris(_id_uri, _other_uri), do: :error diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex @@ -12,6 +12,7 @@ defmodule Pleroma.Object.Fetcher do alias Pleroma.Web.ActivityPub.ObjectValidator alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.Federator + alias Pleroma.Web.FedSockets require Logger require Pleroma.Constants @@ -36,8 +37,7 @@ defmodule Pleroma.Object.Fetcher do defp reinject_object(%Object{data: %{"type" => "Question"}} = object, new_data) do Logger.debug("Reinjecting object #{new_data["id"]}") - with new_data <- Transmogrifier.fix_object(new_data), - data <- maybe_reinject_internal_fields(object, new_data), + with data <- maybe_reinject_internal_fields(object, new_data), {:ok, data, _} <- ObjectValidator.validate(data, %{}), changeset <- Object.change(object, %{data: data}), changeset <- touch_changeset(changeset), @@ -99,8 +99,8 @@ defmodule Pleroma.Object.Fetcher do {:containment, _} -> {:error, "Object containment failed."} - {:transmogrifier, {:error, {:reject, nil}}} -> - {:reject, nil} + {:transmogrifier, {:error, {:reject, e}}} -> + {:reject, e} {:transmogrifier, _} = e -> {:error, e} @@ -183,9 +183,47 @@ defmodule Pleroma.Object.Fetcher do end end - def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do + def fetch_and_contain_remote_object_from_id(prm, opts \\ []) + + def fetch_and_contain_remote_object_from_id(%{"id" => id}, opts), + do: fetch_and_contain_remote_object_from_id(id, opts) + + def fetch_and_contain_remote_object_from_id(id, opts) when is_binary(id) do Logger.debug("Fetching object #{id} via AP") + with {:scheme, true} <- {:scheme, String.starts_with?(id, "http")}, + {:ok, body} <- get_object(id, opts), + {:ok, data} <- safe_json_decode(body), + :ok <- Containment.contain_origin_from_id(id, data) do + {:ok, data} + else + {:scheme, _} -> + {:error, "Unsupported URI scheme"} + + {:error, e} -> + {:error, e} + + e -> + {:error, e} + end + end + + def fetch_and_contain_remote_object_from_id(_id, _opts), + do: {:error, "id must be a string"} + + defp get_object(id, opts) do + with false <- Keyword.get(opts, :force_http, false), + {:ok, fedsocket} <- FedSockets.get_or_create_fed_socket(id) do + Logger.debug("fetching via fedsocket - #{inspect(id)}") + FedSockets.fetch(fedsocket, id) + else + _other -> + Logger.debug("fetching via http - #{inspect(id)}") + get_object_http(id) + end + end + + defp get_object_http(id) do date = Pleroma.Signature.signed_date() headers = @@ -193,20 +231,13 @@ defmodule Pleroma.Object.Fetcher do |> maybe_date_fetch(date) |> sign_fetch(id, date) - Logger.debug("Fetch headers: #{inspect(headers)}") + case HTTP.get(id, headers) do + {:ok, %{body: body, status: code}} when code in 200..299 -> + {:ok, body} - with {:scheme, true} <- {:scheme, String.starts_with?(id, "http")}, - {:ok, %{body: body, status: code}} when code in 200..299 <- HTTP.get(id, headers), - {:ok, data} <- Jason.decode(body), - :ok <- Containment.contain_origin_from_id(id, data) do - {:ok, data} - else {:ok, %{status: code}} when code in [404, 410] -> {:error, "Object has been deleted"} - {:scheme, _} -> - {:error, "Unsupported URI scheme"} - {:error, e} -> {:error, e} @@ -215,8 +246,6 @@ defmodule Pleroma.Object.Fetcher do end end - def fetch_and_contain_remote_object_from_id(%{"id" => id}), - do: fetch_and_contain_remote_object_from_id(id) - - def fetch_and_contain_remote_object_from_id(_id), do: {:error, "id must be a string"} + defp safe_json_decode(nil), do: {:ok, nil} + defp safe_json_decode(json), do: Jason.decode(json) end diff --git a/lib/pleroma/plugs/oauth_scopes_plug.ex b/lib/pleroma/plugs/oauth_scopes_plug.ex @@ -53,7 +53,7 @@ defmodule Pleroma.Plugs.OAuthScopesPlug do |> assign(:token, nil) end - @doc "Filters descendants of supported scopes" + @doc "Keeps those of `scopes` which are descendants of `supported_scopes`" def filter_descendants(scopes, supported_scopes) do Enum.filter( scopes, diff --git a/lib/pleroma/repo.ex b/lib/pleroma/repo.ex @@ -49,7 +49,21 @@ defmodule Pleroma.Repo do end end - def chunk_stream(query, chunk_size) do + @doc """ + Returns a lazy enumerable that emits all entries from the data store matching the given query. + + `returns_as` use to group records. use the `batches` option to fetch records in bulk. + + ## Examples + + # fetch records one-by-one + iex> Pleroma.Repo.chunk_stream(Pleroma.Activity.Queries.by_actor(ap_id), 500) + + # fetch records in bulk + iex> Pleroma.Repo.chunk_stream(Pleroma.Activity.Queries.by_actor(ap_id), 500, :batches) + """ + @spec chunk_stream(Ecto.Query.t(), integer(), atom()) :: Enumerable.t() + def chunk_stream(query, chunk_size, returns_as \\ :one) do # We don't actually need start and end funcitons of resource streaming, # but it seems to be the only way to not fetch records one-by-one and # have individual records be the elements of the stream, instead of @@ -69,7 +83,12 @@ defmodule Pleroma.Repo do records -> last_id = List.last(records).id - {records, last_id} + + if returns_as == :one do + {records, last_id} + else + {[records], last_id} + end end end, fn _ -> :ok end diff --git a/lib/pleroma/repo_streamer.ex b/lib/pleroma/repo_streamer.ex @@ -1,34 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.RepoStreamer do - alias Pleroma.Repo - import Ecto.Query - - def chunk_stream(query, chunk_size) do - Stream.unfold(0, fn - :halt -> - {[], :halt} - - last_id -> - query - |> order_by(asc: :id) - |> where([r], r.id > ^last_id) - |> limit(^chunk_size) - |> Repo.all() - |> case do - [] -> - {[], :halt} - - records -> - last_id = List.last(records).id - {records, last_id} - end - end) - |> Stream.take_while(fn - [] -> false - _ -> true - end) - end -end diff --git a/lib/pleroma/reverse_proxy/client/tesla.ex b/lib/pleroma/reverse_proxy/client/tesla.ex @@ -28,7 +28,7 @@ defmodule Pleroma.ReverseProxy.Client.Tesla do url, body, headers, - Keyword.put(opts, :adapter, opts) + opts ) do if is_map(response.body) and method != :head do {:ok, response.status, response.headers, response.body} diff --git a/lib/pleroma/reverse_proxy/reverse_proxy.ex b/lib/pleroma/reverse_proxy/reverse_proxy.ex @@ -17,6 +17,9 @@ defmodule Pleroma.ReverseProxy do @failed_request_ttl :timer.seconds(60) @methods ~w(GET HEAD) + def max_read_duration_default, do: @max_read_duration + def default_cache_control_header, do: @default_cache_control_header + @moduledoc """ A reverse proxy. @@ -391,6 +394,8 @@ defmodule Pleroma.ReverseProxy do defp body_size_constraint(_, _), do: :ok + defp check_read_duration(nil = _duration, max), do: check_read_duration(@max_read_duration, max) + defp check_read_duration(duration, max) when is_integer(duration) and is_integer(max) and max > 0 do if duration > max do diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex @@ -39,7 +39,7 @@ defmodule Pleroma.Signature do def fetch_public_key(conn) do with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn), {:ok, actor_id} <- key_id_to_actor_id(kid), - {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do + {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id, force_http: true) do {:ok, public_key} else e -> @@ -50,8 +50,8 @@ defmodule Pleroma.Signature do def refetch_public_key(conn) do with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn), {:ok, actor_id} <- key_id_to_actor_id(kid), - {:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id), - {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do + {:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id, force_http: true), + {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id, force_http: true) do {:ok, public_key} else e -> diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex @@ -3,12 +3,15 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Stats do + use GenServer + import Ecto.Query + alias Pleroma.CounterCache alias Pleroma.Repo alias Pleroma.User - use GenServer + @interval :timer.seconds(60) def start_link(_) do GenServer.start_link( @@ -18,6 +21,12 @@ defmodule Pleroma.Stats do ) end + @impl true + def init(_args) do + if Pleroma.Config.get(:env) == :test, do: :ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo) + {:ok, nil, {:continue, :calculate_stats}} + end + @doc "Performs update stats" def force_update do GenServer.call(__MODULE__, :force_update) @@ -29,7 +38,11 @@ defmodule Pleroma.Stats do end @doc "Returns stats data" - @spec get_stats() :: %{domain_count: integer(), status_count: integer(), user_count: integer()} + @spec get_stats() :: %{ + domain_count: non_neg_integer(), + status_count: non_neg_integer(), + user_count: non_neg_integer() + } def get_stats do %{stats: stats} = GenServer.call(__MODULE__, :get_state) @@ -44,25 +57,14 @@ defmodule Pleroma.Stats do peers end - def init(_args) do - {:ok, calculate_stat_data()} - end - - def handle_call(:force_update, _from, _state) do - new_stats = calculate_stat_data() - {:reply, new_stats, new_stats} - end - - def handle_call(:get_state, _from, state) do - {:reply, state, state} - end - - def handle_cast(:run_update, _state) do - new_stats = calculate_stat_data() - - {:noreply, new_stats} - end - + @spec calculate_stat_data() :: %{ + peers: list(), + stats: %{ + domain_count: non_neg_integer(), + status_count: non_neg_integer(), + user_count: non_neg_integer() + } + } def calculate_stat_data do peers = from( @@ -97,6 +99,7 @@ defmodule Pleroma.Stats do } end + @spec get_status_visibility_count(String.t() | nil) :: map() def get_status_visibility_count(instance \\ nil) do if is_nil(instance) do CounterCache.get_sum() @@ -104,4 +107,36 @@ defmodule Pleroma.Stats do CounterCache.get_by_instance(instance) end end + + @impl true + def handle_continue(:calculate_stats, _) do + stats = calculate_stat_data() + Process.send_after(self(), :run_update, @interval) + {:noreply, stats} + end + + @impl true + def handle_call(:force_update, _from, _state) do + new_stats = calculate_stat_data() + {:reply, new_stats, new_stats} + end + + @impl true + def handle_call(:get_state, _from, state) do + {:reply, state, state} + end + + @impl true + def handle_cast(:run_update, _state) do + new_stats = calculate_stat_data() + + {:noreply, new_stats} + end + + @impl true + def handle_info(:run_update, _) do + new_stats = calculate_stat_data() + Process.send_after(self(), :run_update, @interval) + {:noreply, new_stats} + end end diff --git a/lib/pleroma/telemetry/logger.ex b/lib/pleroma/telemetry/logger.ex @@ -7,7 +7,8 @@ defmodule Pleroma.Telemetry.Logger do [:pleroma, :connection_pool, :reclaim, :start], [:pleroma, :connection_pool, :reclaim, :stop], [:pleroma, :connection_pool, :provision_failure], - [:pleroma, :connection_pool, :client_death] + [:pleroma, :connection_pool, :client, :dead], + [:pleroma, :connection_pool, :client, :add] ] def attach do :telemetry.attach_many("pleroma-logger", @events, &handle_event/4, []) @@ -62,7 +63,7 @@ defmodule Pleroma.Telemetry.Logger do end def handle_event( - [:pleroma, :connection_pool, :client_death], + [:pleroma, :connection_pool, :client, :dead], %{client_pid: client_pid, reason: reason}, %{key: key}, _ @@ -73,4 +74,17 @@ defmodule Pleroma.Telemetry.Logger do }" end) end + + def handle_event( + [:pleroma, :connection_pool, :client, :add], + %{clients: [_, _ | _] = clients}, + %{key: key, protocol: :http}, + _ + ) do + Logger.info(fn -> + "Pool worker for #{key}: #{length(clients)} clients are using an HTTP1 connection at the same time, head-of-line blocking might occur." + end) + end + + def handle_event([:pleroma, :connection_pool, :client, :add], _, _, _), do: :ok end diff --git a/lib/pleroma/tesla/middleware/connection_pool.ex b/lib/pleroma/tesla/middleware/connection_pool.ex @@ -0,0 +1,50 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Tesla.Middleware.ConnectionPool do + @moduledoc """ + Middleware to get/release connections from `Pleroma.Gun.ConnectionPool` + """ + + @behaviour Tesla.Middleware + + alias Pleroma.Gun.ConnectionPool + + @impl Tesla.Middleware + def call(%Tesla.Env{url: url, opts: opts} = env, next, _) do + uri = URI.parse(url) + + # Avoid leaking connections when the middleware is called twice + # with body_as: :chunks. We assume only the middleware can set + # opts[:adapter][:conn] + if opts[:adapter][:conn] do + ConnectionPool.release_conn(opts[:adapter][:conn]) + end + + case ConnectionPool.get_conn(uri, opts[:adapter]) do + {:ok, conn_pid} -> + adapter_opts = Keyword.merge(opts[:adapter], conn: conn_pid, close_conn: false) + opts = Keyword.put(opts, :adapter, adapter_opts) + env = %{env | opts: opts} + + case Tesla.run(env, next) do + {:ok, env} -> + unless opts[:adapter][:body_as] == :chunks do + ConnectionPool.release_conn(conn_pid) + {_, res} = pop_in(env.opts[:adapter][:conn]) + {:ok, res} + else + {:ok, env} + end + + err -> + ConnectionPool.release_conn(conn_pid) + err + end + + err -> + err + end + end +end diff --git a/lib/pleroma/tesla/middleware/follow_redirects.ex b/lib/pleroma/tesla/middleware/follow_redirects.ex @@ -1,110 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2015-2020 Tymon Tobolski <https://github.com/teamon/tesla/blob/master/lib/tesla/middleware/follow_redirects.ex> -# Copyright © 2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.HTTP.Middleware.FollowRedirects do - @moduledoc """ - Pool-aware version of https://github.com/teamon/tesla/blob/master/lib/tesla/middleware/follow_redirects.ex - - Follow 3xx redirects - ## Options - - `:max_redirects` - limit number of redirects (default: `5`) - """ - - alias Pleroma.Gun.ConnectionPool - - @behaviour Tesla.Middleware - - @max_redirects 5 - @redirect_statuses [301, 302, 303, 307, 308] - - @impl Tesla.Middleware - def call(env, next, opts \\ []) do - max = Keyword.get(opts, :max_redirects, @max_redirects) - - redirect(env, next, max) - end - - defp redirect(env, next, left) do - opts = env.opts[:adapter] - - case Tesla.run(env, next) do - {:ok, %{status: status} = res} when status in @redirect_statuses and left > 0 -> - release_conn(opts) - - case Tesla.get_header(res, "location") do - nil -> - {:ok, res} - - location -> - location = parse_location(location, res) - - case get_conn(location, opts) do - {:ok, opts} -> - %{env | opts: Keyword.put(env.opts, :adapter, opts)} - |> new_request(res.status, location) - |> redirect(next, left - 1) - - e -> - e - end - end - - {:ok, %{status: status}} when status in @redirect_statuses -> - release_conn(opts) - {:error, {__MODULE__, :too_many_redirects}} - - {:error, _} = e -> - release_conn(opts) - e - - other -> - unless opts[:body_as] == :chunks do - release_conn(opts) - end - - other - end - end - - defp get_conn(location, opts) do - uri = URI.parse(location) - - case ConnectionPool.get_conn(uri, opts) do - {:ok, conn} -> - {:ok, Keyword.merge(opts, conn: conn)} - - e -> - e - end - end - - defp release_conn(opts) do - ConnectionPool.release_conn(opts[:conn]) - end - - # The 303 (See Other) redirect was added in HTTP/1.1 to indicate that the originally - # requested resource is not available, however a related resource (or another redirect) - # available via GET is available at the specified location. - # https://tools.ietf.org/html/rfc7231#section-6.4.4 - defp new_request(env, 303, location), do: %{env | url: location, method: :get, query: []} - - # The 307 (Temporary Redirect) status code indicates that the target - # resource resides temporarily under a different URI and the user agent - # MUST NOT change the request method (...) - # https://tools.ietf.org/html/rfc7231#section-6.4.7 - defp new_request(env, 307, location), do: %{env | url: location} - - defp new_request(env, _, location), do: %{env | url: location, query: []} - - defp parse_location("https://" <> _rest = location, _env), do: location - defp parse_location("http://" <> _rest = location, _env), do: location - - defp parse_location(location, env) do - env.url - |> URI.parse() - |> URI.merge(location) - |> URI.to_string() - end -end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex @@ -25,7 +25,6 @@ defmodule Pleroma.User do alias Pleroma.Object alias Pleroma.Registration alias Pleroma.Repo - alias Pleroma.RepoStreamer alias Pleroma.User alias Pleroma.UserRelationship alias Pleroma.Web @@ -83,7 +82,7 @@ defmodule Pleroma.User do ] schema "users" do - field(:bio, :string) + field(:bio, :string, default: "") field(:raw_bio, :string) field(:email, :string) field(:name, :string) @@ -276,9 +275,9 @@ defmodule Pleroma.User do @spec account_status(User.t()) :: account_status() def account_status(%User{deactivated: true}), do: :deactivated def account_status(%User{password_reset_pending: true}), do: :password_reset_pending - def account_status(%User{approval_pending: true}), do: :approval_pending + def account_status(%User{local: true, approval_pending: true}), do: :approval_pending - def account_status(%User{confirmation_pending: true}) do + def account_status(%User{local: true, confirmation_pending: true}) do if Config.get([:instance, :account_activation_required]) do :confirmation_pending else @@ -1587,7 +1586,7 @@ defmodule Pleroma.User do # "Right to be forgotten" # https://gdpr.eu/right-to-be-forgotten/ change(user, %{ - bio: nil, + bio: "", raw_bio: nil, email: nil, name: nil, @@ -1686,42 +1685,6 @@ defmodule Pleroma.User do def perform(:deactivate_async, user, status), do: deactivate(user, status) - @spec perform(atom(), User.t(), list()) :: list() | {:error, any()} - def perform(:blocks_import, %User{} = blocker, blocked_identifiers) - when is_list(blocked_identifiers) do - Enum.map( - blocked_identifiers, - fn blocked_identifier -> - with {:ok, %User{} = blocked} <- get_or_fetch(blocked_identifier), - {:ok, _block} <- CommonAPI.block(blocker, blocked) do - blocked - else - err -> - Logger.debug("blocks_import failed for #{blocked_identifier} with: #{inspect(err)}") - err - end - end - ) - end - - def perform(:follow_import, %User{} = follower, followed_identifiers) - when is_list(followed_identifiers) do - Enum.map( - followed_identifiers, - fn followed_identifier -> - with {:ok, %User{} = followed} <- get_or_fetch(followed_identifier), - {:ok, follower} <- maybe_direct_follow(follower, followed), - {:ok, _, _, _} <- CommonAPI.follow(follower, followed) do - followed - else - err -> - Logger.debug("follow_import failed for #{followed_identifier} with: #{inspect(err)}") - err - end - end - ) - end - @spec external_users_query() :: Ecto.Query.t() def external_users_query do User.Query.build(%{ @@ -1750,21 +1713,6 @@ defmodule Pleroma.User do Repo.all(query) end - def blocks_import(%User{} = blocker, blocked_identifiers) when is_list(blocked_identifiers) do - BackgroundWorker.enqueue("blocks_import", %{ - "blocker_id" => blocker.id, - "blocked_identifiers" => blocked_identifiers - }) - end - - def follow_import(%User{} = follower, followed_identifiers) - when is_list(followed_identifiers) do - BackgroundWorker.enqueue("follow_import", %{ - "follower_id" => follower.id, - "followed_identifiers" => followed_identifiers - }) - end - def delete_notifications_from_user_activities(%User{ap_id: ap_id}) do Notification |> join(:inner, [n], activity in assoc(n, :activity)) @@ -1775,7 +1723,7 @@ defmodule Pleroma.User do def delete_user_activities(%User{ap_id: ap_id} = user) do ap_id |> Activity.Queries.by_actor() - |> RepoStreamer.chunk_stream(50) + |> Repo.chunk_stream(50, :batches) |> Stream.each(fn activities -> Enum.each(activities, fn activity -> delete_activity(activity, user) end) end) @@ -1821,12 +1769,12 @@ defmodule Pleroma.User do def html_filter_policy(_), do: Config.get([:markup, :scrub_policy]) - def fetch_by_ap_id(ap_id), do: ActivityPub.make_user_from_ap_id(ap_id) + def fetch_by_ap_id(ap_id, opts \\ []), do: ActivityPub.make_user_from_ap_id(ap_id, opts) - def get_or_fetch_by_ap_id(ap_id) do + def get_or_fetch_by_ap_id(ap_id, opts \\ []) do cached_user = get_cached_by_ap_id(ap_id) - maybe_fetched_user = needs_update?(cached_user) && fetch_by_ap_id(ap_id) + maybe_fetched_user = needs_update?(cached_user) && fetch_by_ap_id(ap_id, opts) case {cached_user, maybe_fetched_user} do {_, {:ok, %User{} = user}} -> @@ -1899,8 +1847,8 @@ defmodule Pleroma.User do def public_key(_), do: {:error, "key not found"} - def get_public_key_for_ap_id(ap_id) do - with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id), + def get_public_key_for_ap_id(ap_id, opts \\ []) do + with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id, opts), {:ok, public_key} <- public_key(user) do {:ok, public_key} else @@ -2315,6 +2263,11 @@ defmodule Pleroma.User do max_pinned_statuses = Config.get([:instance, :max_pinned_statuses], 0) params = %{pinned_activities: user.pinned_activities ++ [id]} + # if pinned activity was scheduled for deletion, we remove job + if expiration = Pleroma.Workers.PurgeExpiredActivity.get_expiration(id) do + Oban.cancel_job(expiration.id) + end + user |> cast(params, [:pinned_activities]) |> validate_length(:pinned_activities, @@ -2327,9 +2280,19 @@ defmodule Pleroma.User do |> update_and_set_cache() end - def remove_pinnned_activity(user, %Pleroma.Activity{id: id}) do + def remove_pinnned_activity(user, %Pleroma.Activity{id: id, data: data}) do params = %{pinned_activities: List.delete(user.pinned_activities, id)} + # if pinned activity was scheduled for deletion, we reschedule it for deletion + if data["expires_at"] do + {:ok, expires_at, _} = DateTime.from_iso8601(data["expires_at"]) + + Pleroma.Workers.PurgeExpiredActivity.enqueue(%{ + activity_id: id, + expires_at: expires_at + }) + end + user |> cast(params, [:pinned_activities]) |> update_and_set_cache() diff --git a/lib/pleroma/user/import.ex b/lib/pleroma/user/import.ex @@ -0,0 +1,85 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.User.Import do + use Ecto.Schema + + alias Pleroma.User + alias Pleroma.Web.CommonAPI + alias Pleroma.Workers.BackgroundWorker + + require Logger + + @spec perform(atom(), User.t(), list()) :: :ok | list() | {:error, any()} + def perform(:mutes_import, %User{} = user, [_ | _] = identifiers) do + Enum.map( + identifiers, + fn identifier -> + with {:ok, %User{} = muted_user} <- User.get_or_fetch(identifier), + {:ok, _} <- User.mute(user, muted_user) do + muted_user + else + error -> handle_error(:mutes_import, identifier, error) + end + end + ) + end + + def perform(:blocks_import, %User{} = blocker, [_ | _] = identifiers) do + Enum.map( + identifiers, + fn identifier -> + with {:ok, %User{} = blocked} <- User.get_or_fetch(identifier), + {:ok, _block} <- CommonAPI.block(blocker, blocked) do + blocked + else + error -> handle_error(:blocks_import, identifier, error) + end + end + ) + end + + def perform(:follow_import, %User{} = follower, [_ | _] = identifiers) do + Enum.map( + identifiers, + fn identifier -> + with {:ok, %User{} = followed} <- User.get_or_fetch(identifier), + {:ok, follower} <- User.maybe_direct_follow(follower, followed), + {:ok, _, _, _} <- CommonAPI.follow(follower, followed) do + followed + else + error -> handle_error(:follow_import, identifier, error) + end + end + ) + end + + def perform(_, _, _), do: :ok + + defp handle_error(op, user_id, error) do + Logger.debug("#{op} failed for #{user_id} with: #{inspect(error)}") + error + end + + def blocks_import(%User{} = blocker, [_ | _] = identifiers) do + BackgroundWorker.enqueue( + "blocks_import", + %{"user_id" => blocker.id, "identifiers" => identifiers} + ) + end + + def follow_import(%User{} = follower, [_ | _] = identifiers) do + BackgroundWorker.enqueue( + "follow_import", + %{"user_id" => follower.id, "identifiers" => identifiers} + ) + end + + def mutes_import(%User{} = user, [_ | _] = identifiers) do + BackgroundWorker.enqueue( + "mutes_import", + %{"user_id" => user.id, "identifiers" => identifiers} + ) + end +end diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex @@ -52,6 +52,7 @@ defmodule Pleroma.User.Search do |> base_query(following) |> filter_blocked_user(for_user) |> filter_invisible_users() + |> filter_discoverable_users() |> filter_internal_users() |> filter_blocked_domains(for_user) |> fts_search(query_string) @@ -122,6 +123,10 @@ defmodule Pleroma.User.Search do from(q in query, where: q.invisible == false) end + defp filter_discoverable_users(query) do + from(q in query, where: q.discoverable == true) + end + defp filter_internal_users(query) do from(q in query, where: q.actor_type != "Application") end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do alias Pleroma.Activity alias Pleroma.Activity.Ir.Topics - alias Pleroma.ActivityExpiration alias Pleroma.Config alias Pleroma.Constants alias Pleroma.Conversation @@ -85,7 +84,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp increase_replies_count_if_reply(_create_data), do: :noop - @object_types ~w[ChatMessage Question Answer Audio Event] + @object_types ~w[ChatMessage Question Answer Audio Video Event Article] @spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()} def persist(%{"type" => type} = object, meta) when type in @object_types do with {:ok, object} <- Object.create(object) do @@ -102,7 +101,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do local: local, recipients: recipients, actor: object["actor"] - }) do + }), + # TODO: add tests for expired activities, when Note type will be supported in new pipeline + {:ok, _} <- maybe_create_activity_expiration(activity) do {:ok, activity, meta} end end @@ -111,23 +112,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def insert(map, local \\ true, fake \\ false, bypass_actor_check \\ false) when is_map(map) do with nil <- Activity.normalize(map), map <- lazy_put_activity_defaults(map, fake), - true <- bypass_actor_check || check_actor_is_active(map["actor"]), - {_, true} <- {:remote_limit_error, check_remote_limit(map)}, + {_, true} <- {:actor_check, bypass_actor_check || check_actor_is_active(map["actor"])}, + {_, true} <- {:remote_limit_pass, check_remote_limit(map)}, {:ok, map} <- MRF.filter(map), {recipients, _, _} = get_recipients(map), {:fake, false, map, recipients} <- {:fake, fake, map, recipients}, {:containment, :ok} <- {:containment, Containment.contain_child(map)}, - {:ok, map, object} <- insert_full_object(map) do - {:ok, activity} = - %Activity{ - data: map, - local: local, - actor: map["actor"], - recipients: recipients - } - |> Repo.insert() - |> maybe_create_activity_expiration() - + {:ok, map, object} <- insert_full_object(map), + {:ok, activity} <- insert_activity_with_expiration(map, local, recipients) do # Splice in the child object if we have one. activity = Maps.put_if_present(activity, :object, object) @@ -138,6 +130,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do %Activity{} = activity -> {:ok, activity} + {:actor_check, _} -> + {:error, false} + + {:containment, _} = error -> + error + + {:error, _} = error -> + error + {:fake, true, map, recipients} -> activity = %Activity{ data: map, @@ -150,8 +151,24 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) {:ok, activity} - error -> - {:error, error} + {:remote_limit_pass, _} -> + {:error, :remote_limit} + + {:reject, _} = e -> + {:error, e} + end + end + + defp insert_activity_with_expiration(data, local, recipients) do + struct = %Activity{ + data: data, + local: local, + actor: data["actor"], + recipients: recipients + } + + with {:ok, activity} <- Repo.insert(struct) do + maybe_create_activity_expiration(activity) end end @@ -164,13 +181,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do stream_out_participations(participations) end - defp maybe_create_activity_expiration({:ok, %{data: %{"expires_at" => expires_at}} = activity}) do - with {:ok, _} <- ActivityExpiration.create(activity, expires_at) do + defp maybe_create_activity_expiration( + %{data: %{"expires_at" => %DateTime{} = expires_at}} = activity + ) do + with {:ok, _job} <- + Pleroma.Workers.PurgeExpiredActivity.enqueue(%{ + activity_id: activity.id, + expires_at: expires_at + }) do {:ok, activity} end end - defp maybe_create_activity_expiration(result), do: result + defp maybe_create_activity_expiration(activity), do: {:ok, activity} defp create_or_bump_conversation(activity, actor) do with {:ok, conversation} <- Conversation.create_or_bump_for(activity), @@ -818,7 +841,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do from( [activity, object: o] in query, where: fragment("not (? = ANY(?))", activity.actor, ^blocked_ap_ids), - where: fragment("not (? && ?)", activity.recipients, ^blocked_ap_ids), + where: + fragment( + "((not (? && ?)) or ? = ?)", + activity.recipients, + ^blocked_ap_ids, + activity.actor, + ^user.ap_id + ), where: fragment( "recipients_contain_blocked_domains(?, ?) = false", @@ -1224,7 +1254,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do name: data["name"], follower_address: data["followers"], following_address: data["following"], - bio: data["summary"], + bio: data["summary"] || "", actor_type: actor_type, also_known_as: Map.get(data, "alsoKnownAs", []), public_key: public_key, @@ -1247,10 +1277,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def fetch_follow_information_for_user(user) do with {:ok, following_data} <- - Fetcher.fetch_and_contain_remote_object_from_id(user.following_address), + Fetcher.fetch_and_contain_remote_object_from_id(user.following_address, + force_http: true + ), {:ok, hide_follows} <- collection_private(following_data), {:ok, followers_data} <- - Fetcher.fetch_and_contain_remote_object_from_id(user.follower_address), + Fetcher.fetch_and_contain_remote_object_from_id(user.follower_address, force_http: true), {:ok, hide_followers} <- collection_private(followers_data) do {:ok, %{ @@ -1324,8 +1356,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end - def fetch_and_prepare_user_from_ap_id(ap_id) do - with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id), + def fetch_and_prepare_user_from_ap_id(ap_id, opts \\ []) do + with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id, opts), {:ok, data} <- user_data_from_user_object(data) do {:ok, maybe_update_follow_information(data)} else @@ -1367,13 +1399,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end - def make_user_from_ap_id(ap_id) do + def make_user_from_ap_id(ap_id, opts \\ []) do user = User.get_cached_by_ap_id(ap_id) if user && !User.ap_enabled?(user) do Transmogrifier.upgrade_user_from_ap_id(ap_id) else - with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id) do + with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, opts) do if user do user |> User.remote_user_changeset(data) diff --git a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex @@ -31,10 +31,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy do defp maybe_add_expiration(activity) do days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365) - expires_at = NaiveDateTime.utc_now() |> Timex.shift(days: days) + expires_at = DateTime.utc_now() |> Timex.shift(days: days) with %{"expires_at" => existing_expires_at} <- activity, - :lt <- NaiveDateTime.compare(existing_expires_at, expires_at) do + :lt <- DateTime.compare(existing_expires_at, expires_at) do activity else _ -> Map.put(activity, "expires_at", expires_at) diff --git a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do + alias Pleroma.User + @behaviour Pleroma.Web.ActivityPub.MRF + @moduledoc "Remove bot posts from federated timeline" + + require Pleroma.Constants + + defp check_by_actor_type(user), do: user.actor_type in ["Application", "Service"] + defp check_by_nickname(user), do: Regex.match?(~r/bot@|ebooks@/i, user.nickname) + + defp check_if_bot(user), do: check_by_actor_type(user) or check_by_nickname(user) + + @impl true + def filter( + %{ + "type" => "Create", + "to" => to, + "cc" => cc, + "actor" => actor, + "object" => object + } = message + ) do + user = User.get_cached_by_ap_id(actor) + isbot = check_if_bot(user) + + if isbot and Enum.member?(to, Pleroma.Constants.as_public()) do + to = List.delete(to, Pleroma.Constants.as_public()) ++ [user.follower_address] + cc = List.delete(cc, user.follower_address) ++ [Pleroma.Constants.as_public()] + + object = + object + |> Map.put("to", to) + |> Map.put("cc", cc) + + message = + message + |> Map.put("to", to) + |> Map.put("cc", cc) + |> Map.put("object", object) + + {:ok, message} + else + {:ok, message} + end + end + + @impl true + def filter(message), do: {:ok, message} + + @impl true + def describe, do: {:ok, %{}} +end diff --git a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex @@ -12,23 +12,21 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do require Logger - @options [ - pool: :media + @adapter_options [ + pool: :media, + recv_timeout: 10_000 ] def perform(:prefetch, url) do - Logger.debug("Prefetching #{inspect(url)}") + # Fetching only proxiable resources + if MediaProxy.enabled?() and MediaProxy.url_proxiable?(url) do + # If preview proxy is enabled, it'll also hit media proxy (so we're caching both requests) + prefetch_url = MediaProxy.preview_url(url) - opts = - if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Hackney do - Keyword.put(@options, :recv_timeout, 10_000) - else - @options - end + Logger.debug("Prefetching #{inspect(url)} as #{inspect(prefetch_url)}") - url - |> MediaProxy.url() - |> HTTP.get([], adapter: opts) + HTTP.get(prefetch_url, [], @adapter_options) + end end def perform(:preload, %{"object" => %{"attachment" => attachments}} = _message) do diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex @@ -12,11 +12,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.Activity alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Object + alias Pleroma.Object.Containment alias Pleroma.User alias Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator - alias Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator @@ -149,10 +151,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do end end - def validate(%{"type" => "Audio"} = object, meta) do + def validate(%{"type" => type} = object, meta) when type in ~w[Audio Video] do with {:ok, object} <- object - |> AudioValidator.cast_and_validate() + |> AudioVideoValidator.cast_and_validate() + |> Ecto.Changeset.apply_action(:insert) do + object = stringify_keys(object) + {:ok, object, meta} + end + end + + def validate(%{"type" => "Article"} = object, meta) do + with {:ok, object} <- + object + |> ArticleNoteValidator.cast_and_validate() |> Ecto.Changeset.apply_action(:insert) do object = stringify_keys(object) {:ok, object, meta} @@ -198,7 +210,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do %{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity, meta ) - when objtype in ~w[Question Answer Audio Event] do + when objtype in ~w[Question Answer Audio Video Event Article] do with {:ok, object_data} <- cast_and_apply(object), meta = Keyword.put(meta, :object_data, object_data |> stringify_keys), {:ok, create_activity} <- @@ -232,14 +244,18 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do AnswerValidator.cast_and_apply(object) end - def cast_and_apply(%{"type" => "Audio"} = object) do - AudioValidator.cast_and_apply(object) + def cast_and_apply(%{"type" => type} = object) when type in ~w[Audio Video] do + AudioVideoValidator.cast_and_apply(object) end def cast_and_apply(%{"type" => "Event"} = object) do EventValidator.cast_and_apply(object) end + def cast_and_apply(%{"type" => "Article"} = object) do + ArticleNoteValidator.cast_and_apply(object) + end + def cast_and_apply(o), do: {:error, {:validator_not_set, o}} # is_struct/1 isn't present in Elixir 1.8.x @@ -262,7 +278,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do def stringify_keys(object), do: object def fetch_actor(object) do - with {:ok, actor} <- ObjectValidators.ObjectID.cast(object["actor"]) do + with actor <- Containment.get_actor(object), + {:ok, actor} <- ObjectValidators.ObjectID.cast(actor) do User.get_or_fetch_by_ap_id(actor) end end diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_validator.ex @@ -0,0 +1,106 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator do + use Ecto.Schema + + alias Pleroma.EctoType.ActivityPub.ObjectValidators + alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + alias Pleroma.Web.ActivityPub.Transmogrifier + + import Ecto.Changeset + + @primary_key false + @derive Jason.Encoder + + embedded_schema do + field(:id, ObjectValidators.ObjectID, primary_key: true) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) + # TODO: Write type + field(:tag, {:array, :map}, default: []) + field(:type, :string) + + field(:name, :string) + field(:summary, :string) + field(:content, :string) + + field(:context, :string) + # short identifier for PleromaFE to group statuses by context + field(:context_id, :integer) + + # TODO: Remove actor on objects + field(:actor, ObjectValidators.ObjectID) + + field(:attributedTo, ObjectValidators.ObjectID) + field(:published, ObjectValidators.DateTime) + field(:emoji, ObjectValidators.Emoji, default: %{}) + field(:sensitive, :boolean, default: false) + embeds_many(:attachment, AttachmentValidator) + field(:replies_count, :integer, default: 0) + field(:like_count, :integer, default: 0) + field(:announcement_count, :integer, default: 0) + field(:inReplyTo, ObjectValidators.ObjectID) + field(:url, ObjectValidators.Uri) + + field(:likes, {:array, ObjectValidators.ObjectID}, default: []) + field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) + end + + def cast_and_apply(data) do + data + |> cast_data + |> apply_action(:insert) + end + + def cast_and_validate(data) do + data + |> cast_data() + |> validate_data() + end + + def cast_data(data) do + data = fix(data) + + %__MODULE__{} + |> changeset(data) + end + + defp fix_url(%{"url" => url} = data) when is_map(url) do + Map.put(data, "url", url["href"]) + end + + defp fix_url(data), do: data + + defp fix(data) do + data + |> CommonFixes.fix_defaults() + |> CommonFixes.fix_attribution() + |> CommonFixes.fix_actor() + |> fix_url() + |> Transmogrifier.fix_emoji() + end + + def changeset(struct, data) do + data = fix(data) + + struct + |> cast(data, __schema__(:fields) -- [:attachment]) + |> cast_embed(:attachment) + end + + def validate_data(data_cng) do + data_cng + |> validate_inclusion(:type, ["Article", "Note"]) + |> validate_required([:id, :actor, :attributedTo, :type, :context, :context_id]) + |> CommonValidations.validate_any_presence([:cc, :to]) + |> CommonValidations.validate_fields_match([:actor, :attributedTo]) + |> CommonValidations.validate_actor_presence() + |> CommonValidations.validate_host_match() + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do use Ecto.Schema + alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Web.ActivityPub.ObjectValidators.UrlObjectValidator import Ecto.Changeset @@ -15,7 +16,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do field(:mediaType, :string, default: "application/octet-stream") field(:name, :string) - embeds_many(:url, UrlObjectValidator) + embeds_many :url, UrlObjectValidator, primary_key: false do + field(:type, :string) + field(:href, ObjectValidators.Uri) + field(:mediaType, :string, default: "application/octet-stream") + end end def cast_and_validate(data) do @@ -37,7 +42,18 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do struct |> cast(data, [:type, :mediaType, :name]) - |> cast_embed(:url, required: true) + |> cast_embed(:url, with: &url_changeset/2) + |> validate_inclusion(:type, ~w[Link Document Audio Image Video]) + |> validate_required([:type, :mediaType, :url]) + end + + def url_changeset(struct, data) do + data = fix_media_type(data) + + struct + |> cast(data, [:type, :href, :mediaType]) + |> validate_inclusion(:type, ["Link"]) + |> validate_required([:type, :href, :mediaType]) end def fix_media_type(data) do @@ -75,6 +91,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do def validate_data(cng) do cng + |> validate_inclusion(:type, ~w[Document Audio Image Video]) |> validate_required([:mediaType, :url, :type]) end end diff --git a/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex @@ -1,106 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do - use Ecto.Schema - - alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator - alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes - alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations - - import Ecto.Changeset - - @primary_key false - @derive Jason.Encoder - - embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:bto, ObjectValidators.Recipients, default: []) - field(:bcc, ObjectValidators.Recipients, default: []) - # TODO: Write type - field(:tag, {:array, :map}, default: []) - field(:type, :string) - field(:content, :string) - field(:context, :string) - - # TODO: Remove actor on objects - field(:actor, ObjectValidators.ObjectID) - - field(:attributedTo, ObjectValidators.ObjectID) - field(:summary, :string) - field(:published, ObjectValidators.DateTime) - # TODO: Write type - field(:emoji, :map, default: %{}) - field(:sensitive, :boolean, default: false) - embeds_many(:attachment, AttachmentValidator) - field(:replies_count, :integer, default: 0) - field(:like_count, :integer, default: 0) - field(:announcement_count, :integer, default: 0) - field(:inReplyTo, :string) - field(:url, ObjectValidators.Uri) - # short identifier for PleromaFE to group statuses by context - field(:context_id, :integer) - - field(:likes, {:array, :string}, default: []) - field(:announcements, {:array, :string}, default: []) - end - - def cast_and_apply(data) do - data - |> cast_data - |> apply_action(:insert) - end - - def cast_and_validate(data) do - data - |> cast_data() - |> validate_data() - end - - def cast_data(data) do - %__MODULE__{} - |> changeset(data) - end - - defp fix_url(%{"url" => url} = data) when is_list(url) do - attachment = - Enum.find(url, fn x -> is_map(x) and String.starts_with?(x["mimeType"], "audio/") end) - - link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end) - - data - |> Map.put("attachment", [attachment]) - |> Map.put("url", link_element["href"]) - end - - defp fix_url(data), do: data - - defp fix(data) do - data - |> CommonFixes.fix_defaults() - |> CommonFixes.fix_attribution() - |> fix_url() - end - - def changeset(struct, data) do - data = fix(data) - - struct - |> cast(data, __schema__(:fields) -- [:attachment]) - |> cast_embed(:attachment) - end - - def validate_data(data_cng) do - data_cng - |> validate_inclusion(:type, ["Audio"]) - |> validate_required([:id, :actor, :attributedTo, :type, :context, :attachment]) - |> CommonValidations.validate_any_presence([:cc, :to]) - |> CommonValidations.validate_fields_match([:actor, :attributedTo]) - |> CommonValidations.validate_actor_presence() - |> CommonValidations.validate_host_match() - end -end diff --git a/lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex b/lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex @@ -0,0 +1,134 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do + use Ecto.Schema + + alias Pleroma.EarmarkRenderer + alias Pleroma.EctoType.ActivityPub.ObjectValidators + alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + alias Pleroma.Web.ActivityPub.Transmogrifier + + import Ecto.Changeset + + @primary_key false + @derive Jason.Encoder + + embedded_schema do + field(:id, ObjectValidators.ObjectID, primary_key: true) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) + # TODO: Write type + field(:tag, {:array, :map}, default: []) + field(:type, :string) + + field(:name, :string) + field(:summary, :string) + field(:content, :string) + + field(:context, :string) + # short identifier for PleromaFE to group statuses by context + field(:context_id, :integer) + + # TODO: Remove actor on objects + field(:actor, ObjectValidators.ObjectID) + + field(:attributedTo, ObjectValidators.ObjectID) + field(:published, ObjectValidators.DateTime) + field(:emoji, ObjectValidators.Emoji, default: %{}) + field(:sensitive, :boolean, default: false) + embeds_many(:attachment, AttachmentValidator) + field(:replies_count, :integer, default: 0) + field(:like_count, :integer, default: 0) + field(:announcement_count, :integer, default: 0) + field(:inReplyTo, ObjectValidators.ObjectID) + field(:url, ObjectValidators.Uri) + + field(:likes, {:array, ObjectValidators.ObjectID}, default: []) + field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) + end + + def cast_and_apply(data) do + data + |> cast_data + |> apply_action(:insert) + end + + def cast_and_validate(data) do + data + |> cast_data() + |> validate_data() + end + + def cast_data(data) do + %__MODULE__{} + |> changeset(data) + end + + defp fix_url(%{"url" => url} = data) when is_list(url) do + attachment = + Enum.find(url, fn x -> + mime_type = x["mimeType"] || x["mediaType"] || "" + + is_map(x) and String.starts_with?(mime_type, ["video/", "audio/"]) + end) + + link_element = + Enum.find(url, fn x -> + mime_type = x["mimeType"] || x["mediaType"] || "" + + is_map(x) and mime_type == "text/html" + end) + + data + |> Map.put("attachment", [attachment]) + |> Map.put("url", link_element["href"]) + end + + defp fix_url(data), do: data + + defp fix_content(%{"mediaType" => "text/markdown", "content" => content} = data) + when is_binary(content) do + content = + content + |> Earmark.as_html!(%Earmark.Options{renderer: EarmarkRenderer}) + |> Pleroma.HTML.filter_tags() + + Map.put(data, "content", content) + end + + defp fix_content(data), do: data + + defp fix(data) do + data + |> CommonFixes.fix_defaults() + |> CommonFixes.fix_attribution() + |> CommonFixes.fix_actor() + |> Transmogrifier.fix_emoji() + |> fix_url() + |> fix_content() + end + + def changeset(struct, data) do + data = fix(data) + + struct + |> cast(data, __schema__(:fields) -- [:attachment]) + |> cast_embed(:attachment) + end + + def validate_data(data_cng) do + data_cng + |> validate_inclusion(:type, ["Audio", "Video"]) + |> validate_required([:id, :actor, :attributedTo, :type, :context, :attachment]) + |> CommonValidations.validate_any_presence([:cc, :to]) + |> CommonValidations.validate_fields_match([:actor, :attributedTo]) + |> CommonValidations.validate_actor_presence() + |> CommonValidations.validate_host_match() + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex b/lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex @@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do field(:content, ObjectValidators.SafeText) field(:actor, ObjectValidators.ObjectID) field(:published, ObjectValidators.DateTime) - field(:emoji, :map, default: %{}) + field(:emoji, ObjectValidators.Emoji, default: %{}) embeds_one(:attachment, AttachmentValidator) end diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex @@ -3,6 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do + alias Pleroma.Object.Containment alias Pleroma.Web.ActivityPub.Utils # based on Pleroma.Web.ActivityPub.Utils.lazy_put_objects_defaults @@ -11,12 +12,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do Utils.create_context(data["context"] || data["conversation"]) data - |> Map.put_new("context", context) - |> Map.put_new("context_id", context_id) + |> Map.put("context", context) + |> Map.put("context_id", context_id) end def fix_attribution(data) do data |> Map.put_new("actor", data["attributedTo"]) end + + def fix_actor(data) do + actor = Containment.get_actor(data) + + data + |> Map.put("actor", actor) + |> Map.put("attributedTo", actor) + end end diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -10,9 +10,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Object + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations import Ecto.Changeset - import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations @primary_key false @@ -75,14 +76,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do data |> fix_context(meta) |> fix_addressing(meta) + |> CommonFixes.fix_actor() end def validate_data(cng, meta \\ []) do cng |> validate_required([:actor, :type, :object]) |> validate_inclusion(:type, ["Create"]) - |> validate_actor_presence() - |> validate_any_presence([:to, :cc]) + |> CommonValidations.validate_actor_presence() + |> CommonValidations.validate_any_presence([:to, :cc]) |> validate_actors_match(meta) |> validate_context_match(meta) |> validate_object_nonexistence() diff --git a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex @@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + alias Pleroma.Web.ActivityPub.Transmogrifier import Ecto.Changeset @@ -39,8 +40,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do field(:attributedTo, ObjectValidators.ObjectID) field(:published, ObjectValidators.DateTime) - # TODO: Write type - field(:emoji, :map, default: %{}) + field(:emoji, ObjectValidators.Emoji, default: %{}) field(:sensitive, :boolean, default: false) embeds_many(:attachment, AttachmentValidator) field(:replies_count, :integer, default: 0) @@ -74,6 +74,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do data |> CommonFixes.fix_defaults() |> CommonFixes.fix_attribution() + |> Transmogrifier.fix_emoji() end def changeset(struct, data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex @@ -1,66 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do - use Ecto.Schema - - alias Pleroma.EctoType.ActivityPub.ObjectValidators - - import Ecto.Changeset - - @primary_key false - - embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:bto, ObjectValidators.Recipients, default: []) - field(:bcc, ObjectValidators.Recipients, default: []) - # TODO: Write type - field(:tag, {:array, :map}, default: []) - field(:type, :string) - - field(:name, :string) - field(:summary, :string) - field(:content, :string) - - field(:context, :string) - # short identifier for PleromaFE to group statuses by context - field(:context_id, :integer) - - field(:actor, ObjectValidators.ObjectID) - field(:attributedTo, ObjectValidators.ObjectID) - field(:published, ObjectValidators.DateTime) - # TODO: Write type - field(:emoji, :map, default: %{}) - field(:sensitive, :boolean, default: false) - # TODO: Write type - field(:attachment, {:array, :map}, default: []) - field(:replies_count, :integer, default: 0) - field(:like_count, :integer, default: 0) - field(:announcement_count, :integer, default: 0) - field(:inReplyTo, ObjectValidators.ObjectID) - field(:url, ObjectValidators.Uri) - - field(:likes, {:array, :string}, default: []) - field(:announcements, {:array, :string}, default: []) - end - - def cast_and_validate(data) do - data - |> cast_data() - |> validate_data() - end - - def cast_data(data) do - %__MODULE__{} - |> cast(data, __schema__(:fields)) - end - - def validate_data(data_cng) do - data_cng - |> validate_inclusion(:type, ["Note"]) - |> validate_required([:id, :actor, :to, :cc, :type, :content, :context]) - end -end diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator + alias Pleroma.Web.ActivityPub.Transmogrifier import Ecto.Changeset @@ -35,8 +36,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do field(:attributedTo, ObjectValidators.ObjectID) field(:summary, :string) field(:published, ObjectValidators.DateTime) - # TODO: Write type - field(:emoji, :map, default: %{}) + field(:emoji, ObjectValidators.Emoji, default: %{}) field(:sensitive, :boolean, default: false) embeds_many(:attachment, AttachmentValidator) field(:replies_count, :integer, default: 0) @@ -47,8 +47,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do # short identifier for PleromaFE to group statuses by context field(:context_id, :integer) - field(:likes, {:array, :string}, default: []) - field(:announcements, {:array, :string}, default: []) + field(:likes, {:array, ObjectValidators.ObjectID}, default: []) + field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) field(:closed, ObjectValidators.DateTime) field(:voters, {:array, ObjectValidators.ObjectID}, default: []) @@ -85,6 +85,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do data |> CommonFixes.fix_defaults() |> CommonFixes.fix_attribution() + |> Transmogrifier.fix_emoji() |> fix_closed() end diff --git a/lib/pleroma/web/activity_pub/object_validators/url_object_validator.ex b/lib/pleroma/web/activity_pub/object_validators/url_object_validator.ex @@ -1,24 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.ActivityPub.ObjectValidators.UrlObjectValidator do - use Ecto.Schema - - alias Pleroma.EctoType.ActivityPub.ObjectValidators - - import Ecto.Changeset - @primary_key false - - embedded_schema do - field(:type, :string) - field(:href, ObjectValidators.Uri) - field(:mediaType, :string, default: "application/octet-stream") - end - - def changeset(struct, data) do - struct - |> cast(data, __schema__(:fields)) - |> validate_required([:type, :href, :mediaType]) - end -end diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex @@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do alias Pleroma.User alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.FedSockets require Pleroma.Constants @@ -50,15 +51,35 @@ defmodule Pleroma.Web.ActivityPub.Publisher do def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do Logger.debug("Federating #{id} to #{inbox}") - uri = URI.parse(inbox) + case FedSockets.get_or_create_fed_socket(inbox) do + {:ok, fedsocket} -> + Logger.debug("publishing via fedsockets - #{inspect(inbox)}") + FedSockets.publish(fedsocket, json) + _ -> + Logger.debug("publishing via http - #{inspect(inbox)}") + http_publish(inbox, actor, json, params) + end + end + + def publish_one(%{actor_id: actor_id} = params) do + actor = User.get_cached_by_id(actor_id) + + params + |> Map.delete(:actor_id) + |> Map.put(:actor, actor) + |> publish_one() + end + + defp http_publish(inbox, actor, json, params) do + uri = %{path: path} = URI.parse(inbox) digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64()) date = Pleroma.Signature.signed_date() signature = Pleroma.Signature.sign(actor, %{ - "(request-target)": "post #{uri.path}", + "(request-target)": "post #{path}", host: signature_host(uri), "content-length": byte_size(json), digest: digest, @@ -89,15 +110,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do end end - def publish_one(%{actor_id: actor_id} = params) do - actor = User.get_cached_by_id(actor_id) - - params - |> Map.delete(:actor_id) - |> Map.put(:actor, actor) - |> publish_one() - end - defp signature_host(%URI{port: port, scheme: scheme, host: host}) do if port == URI.default_port(scheme) do host diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex @@ -7,7 +7,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do """ alias Pleroma.Activity alias Pleroma.Activity.Ir.Topics - alias Pleroma.ActivityExpiration alias Pleroma.Chat alias Pleroma.Chat.MessageReference alias Pleroma.FollowingRelationship @@ -188,10 +187,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do Object.increase_replies_count(in_reply_to) end - if expires_at = activity.data["expires_at"] do - ActivityExpiration.create(activity, expires_at) - end - BackgroundWorker.enqueue("fetch_data_for_activity", %{"activity_id" => activity.id}) meta = @@ -341,7 +336,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do end def handle_object_creation(%{"type" => objtype} = object, meta) - when objtype in ~w[Audio Question Event] do + when objtype in ~w[Audio Video Question Event Article] do with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do {:ok, object, meta} end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -7,7 +7,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do A module to handle coding from internal to wire ActivityPub and back. """ alias Pleroma.Activity - alias Pleroma.EarmarkRenderer alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Maps alias Pleroma.Object @@ -45,7 +44,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> fix_addressing |> fix_summary |> fix_type(options) - |> fix_content end def fix_summary(%{"summary" => nil} = object) do @@ -168,7 +166,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options) when not is_nil(in_reply_to) do in_reply_to_id = prepare_in_reply_to(in_reply_to) - object = Map.put(object, "inReplyToAtomUri", in_reply_to_id) depth = (options[:depth] || 0) + 1 if Federator.allowed_thread_distance?(depth) do @@ -176,9 +173,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do %Activity{} <- Activity.get_create_by_object_ap_id(replied_object.data["id"]) do object |> Map.put("inReplyTo", replied_object.data["id"]) - |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id) |> Map.put("context", replied_object.data["context"] || object["conversation"]) - |> Map.drop(["conversation"]) + |> Map.drop(["conversation", "inReplyToAtomUri"]) else e -> Logger.warn("Couldn't fetch #{inspect(in_reply_to_id)}, error: #{inspect(e)}") @@ -276,24 +272,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do Map.put(object, "url", url["href"]) end - def fix_url(%{"type" => "Video", "url" => url} = object) when is_list(url) do - attachment = - Enum.find(url, fn x -> - media_type = x["mediaType"] || x["mimeType"] || "" - - is_map(x) and String.starts_with?(media_type, "video/") - end) - - link_element = - Enum.find(url, fn x -> is_map(x) and (x["mediaType"] || x["mimeType"]) == "text/html" end) - - object - |> Map.put("attachment", [attachment]) - |> Map.put("url", link_element["href"]) - end - - def fix_url(%{"type" => object_type, "url" => url} = object) - when object_type != "Video" and is_list(url) do + def fix_url(%{"url" => url} = object) when is_list(url) do first_element = Enum.at(url, 0) url_string = @@ -318,9 +297,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do Map.put(mapping, name, data["icon"]["url"]) end) - # we merge mastodon and pleroma emoji into a single mapping, to allow for both wire formats - emoji = Map.merge(object["emoji"] || %{}, emoji) - Map.put(object, "emoji", emoji) end @@ -376,18 +352,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def fix_type(object, _), do: object - defp fix_content(%{"mediaType" => "text/markdown", "content" => content} = object) - when is_binary(content) do - html_content = - content - |> Earmark.as_html!(%Earmark.Options{renderer: EarmarkRenderer}) - |> Pleroma.HTML.filter_tags() - - Map.merge(object, %{"content" => html_content, "mediaType" => "text/html"}) - end - - defp fix_content(object), do: object - # Reduce the object list to find the reported user. defp get_reported(objects) do Enum.reduce_while(objects, nil, fn ap_id, _ -> @@ -460,7 +424,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do %{"type" => "Create", "object" => %{"type" => objtype} = object} = data, options ) - when objtype in ~w{Article Note Video Page} do + when objtype in ~w{Note Page} do actor = Containment.get_actor(data) with nil <- Activity.get_create_by_object_ap_id(object["id"]), @@ -554,7 +518,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do %{"type" => "Create", "object" => %{"type" => objtype}} = data, _options ) - when objtype in ~w{Question Answer ChatMessage Audio Event} do + when objtype in ~w{Question Answer ChatMessage Audio Video Event Article} do + data = Map.put(data, "object", strip_internal_fields(data["object"])) + with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do {:ok, activity} @@ -1034,7 +1000,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do def upgrade_user_from_ap_id(ap_id) do with %User{local: false} = user <- User.get_cached_by_ap_id(ap_id), - {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id), + {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id, force_http: true), {:ok, user} <- update_user(user, data) do TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id}) {:ok, user} diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -23,8 +23,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do alias Pleroma.Web.Endpoint alias Pleroma.Web.Router - require Logger - @users_page_size 50 plug( @@ -70,6 +68,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do plug( OAuthScopesPlug, + %{scopes: ["read:chats"], admin: true} + when action in [:list_user_chats] + ) + + plug( + OAuthScopesPlug, %{scopes: ["read"], admin: true} when action in [ :list_log, @@ -256,6 +260,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end end + def list_user_chats(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname} = _params) do + with %User{id: user_id} <- User.get_cached_by_nickname_or_id(nickname, for: admin) do + chats = + Pleroma.Chat.for_user_query(user_id) + |> Pleroma.Repo.all() + + conn + |> put_view(AdminAPI.ChatView) + |> render("index.json", chats: chats) + else + _ -> {:error, :not_found} + end + end + def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do user = User.get_cached_by_nickname(nickname) diff --git a/lib/pleroma/web/admin_api/controllers/chat_controller.ex b/lib/pleroma/web/admin_api/controllers/chat_controller.ex @@ -0,0 +1,85 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.ChatController do + use Pleroma.Web, :controller + + alias Pleroma.Activity + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference + alias Pleroma.ModerationLog + alias Pleroma.Pagination + alias Pleroma.Plugs.OAuthScopesPlug + alias Pleroma.Web.AdminAPI + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView + + require Logger + + plug(Pleroma.Web.ApiSpec.CastAndValidate) + + plug( + OAuthScopesPlug, + %{scopes: ["read:chats"], admin: true} when action in [:show, :messages] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:chats"], admin: true} when action in [:delete_message] + ) + + action_fallback(Pleroma.Web.AdminAPI.FallbackController) + + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ChatOperation + + def delete_message(%{assigns: %{user: user}} = conn, %{ + message_id: message_id, + id: chat_id + }) do + with %MessageReference{object: %{data: %{"id" => object_ap_id}}} = cm_ref <- + MessageReference.get_by_id(message_id), + ^chat_id <- to_string(cm_ref.chat_id), + %Activity{id: activity_id} <- Activity.get_create_by_object_ap_id(object_ap_id), + {:ok, _} <- CommonAPI.delete(activity_id, user) do + ModerationLog.insert_log(%{ + action: "chat_message_delete", + actor: user, + subject_id: message_id + }) + + conn + |> put_view(MessageReferenceView) + |> render("show.json", chat_message_reference: cm_ref) + else + _e -> + {:error, :could_not_delete} + end + end + + def messages(conn, %{id: id} = params) do + with %Chat{} = chat <- Chat.get_by_id(id) do + cm_refs = + chat + |> MessageReference.for_chat_query() + |> Pagination.fetch_paginated(params) + + conn + |> put_view(MessageReferenceView) + |> render("index.json", chat_message_references: cm_refs) + else + _ -> + conn + |> put_status(:not_found) + |> json(%{error: "not found"}) + end + end + + def show(conn, %{id: id}) do + with %Chat{} = chat <- Chat.get_by_id(id) do + conn + |> put_view(AdminAPI.ChatView) + |> render("show.json", chat: chat) + end + end +end diff --git a/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex b/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex @@ -0,0 +1,41 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do + use Pleroma.Web, :controller + + alias Pleroma.Plugs.InstanceStatic + alias Pleroma.Plugs.OAuthScopesPlug + alias Pleroma.Web.InstanceDocument + + plug(Pleroma.Web.ApiSpec.CastAndValidate) + + action_fallback(Pleroma.Web.AdminAPI.FallbackController) + + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation + + plug(OAuthScopesPlug, %{scopes: ["read"], admin: true} when action == :show) + plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action in [:update, :delete]) + + def show(conn, %{name: document_name}) do + with {:ok, url} <- InstanceDocument.get(document_name), + {:ok, content} <- File.read(InstanceStatic.file_path(url)) do + conn + |> put_resp_content_type("text/html") + |> send_resp(200, content) + end + end + + def update(%{body_params: %{file: file}} = conn, %{name: document_name}) do + with {:ok, url} <- InstanceDocument.put(document_name, file.path) do + json(conn, %{"url" => url}) + end + end + + def delete(conn, %{name: document_name}) do + with :ok <- InstanceDocument.delete(document_name) do + json(conn, %{}) + end + end +end diff --git a/lib/pleroma/web/admin_api/views/chat_view.ex b/lib/pleroma/web/admin_api/views/chat_view.ex @@ -0,0 +1,30 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.ChatView do + use Pleroma.Web, :view + + alias Pleroma.Chat + alias Pleroma.User + alias Pleroma.Web.MastodonAPI + alias Pleroma.Web.PleromaAPI + + def render("index.json", %{chats: chats} = opts) do + render_many(chats, __MODULE__, "show.json", Map.delete(opts, :chats)) + end + + def render("show.json", %{chat: %Chat{user_id: user_id}} = opts) do + user = User.get_by_id(user_id) + sender = MastodonAPI.AccountView.render("show.json", user: user, skip_visibility_check: true) + + serialized_chat = PleromaAPI.ChatView.render("show.json", opts) + + serialized_chat + |> Map.put(:sender, sender) + |> Map.put(:receiver, serialized_chat[:account]) + |> Map.delete(:account) + end + + def render(view, opts), do: PleromaAPI.ChatView.render(view, opts) +end diff --git a/lib/pleroma/web/admin_api/views/status_view.ex b/lib/pleroma/web/admin_api/views/status_view.ex @@ -8,6 +8,7 @@ defmodule Pleroma.Web.AdminAPI.StatusView do require Pleroma.Constants alias Pleroma.Web.AdminAPI + alias Pleroma.Web.CommonAPI alias Pleroma.Web.MastodonAPI defdelegate merge_account_views(user), to: AdminAPI.AccountView @@ -17,7 +18,7 @@ defmodule Pleroma.Web.AdminAPI.StatusView do end def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do - user = MastodonAPI.StatusView.get_user(activity.data["actor"]) + user = CommonAPI.get_user(activity.data["actor"]) MastodonAPI.StatusView.render("show.json", opts) |> Map.merge(%{account: merge_account_views(user)}) diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex @@ -13,10 +13,15 @@ defmodule Pleroma.Web.ApiSpec do @impl OpenApi def spec do %OpenApi{ - servers: [ - # Populate the Server info from a phoenix endpoint - OpenApiSpex.Server.from_endpoint(Endpoint) - ], + servers: + if Phoenix.Endpoint.server?(:pleroma, Endpoint) do + [ + # Populate the Server info from a phoenix endpoint + OpenApiSpex.Server.from_endpoint(Endpoint) + ] + else + [] + end, info: %OpenApiSpex.Info{ title: "Pleroma", description: Application.spec(:pleroma, :description) |> to_string(), diff --git a/lib/pleroma/web/api_spec/helpers.ex b/lib/pleroma/web/api_spec/helpers.ex @@ -72,7 +72,11 @@ defmodule Pleroma.Web.ApiSpec.Helpers do end def empty_array_response do - Operation.response("Empty array", "application/json", %Schema{type: :array, example: []}) + Operation.response("Empty array", "application/json", %Schema{ + type: :array, + items: %Schema{type: :object, example: %{}}, + example: [] + }) end def no_content_response do diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -372,6 +372,10 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do tags: ["accounts"], summary: "Identity proofs", operationId: "AccountController.identity_proofs", + # Validators complains about unused path params otherwise + parameters: [ + %Reference{"$ref": "#/components/parameters/accountIdOrNickname"} + ], description: "Not implemented", responses: %{ 200 => empty_array_response() @@ -469,7 +473,6 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do identifier: %Schema{type: :string}, message: %Schema{type: :string} }, - required: [], # Note: example of successful registration with failed login response: # example: %{ # "identifier" => "missing_confirmed_email", @@ -530,7 +533,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do nullable: true, oneOf: [ %Schema{type: :array, items: attribute_field()}, - %Schema{type: :object, additionalProperties: %Schema{type: attribute_field()}} + %Schema{type: :object, additionalProperties: attribute_field()} ] }, # NOTE: `source` field is not supported diff --git a/lib/pleroma/web/api_spec/operations/admin/chat_operation.ex b/lib/pleroma/web/api_spec/operations/admin/chat_operation.ex @@ -0,0 +1,96 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.Admin.ChatOperation do + alias OpenApiSpex.Operation + alias Pleroma.Web.ApiSpec.Schemas.Chat + alias Pleroma.Web.ApiSpec.Schemas.ChatMessage + + import Pleroma.Web.ApiSpec.Helpers + + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def delete_message_operation do + %Operation{ + tags: ["admin", "chat"], + summary: "Delete an individual chat message", + operationId: "AdminAPI.ChatController.delete_message", + parameters: [ + Operation.parameter(:id, :path, :string, "The ID of the Chat"), + Operation.parameter(:message_id, :path, :string, "The ID of the message") + ], + responses: %{ + 200 => + Operation.response( + "The deleted ChatMessage", + "application/json", + ChatMessage + ) + }, + security: [ + %{ + "oAuth" => ["write:chats"] + } + ] + } + end + + def messages_operation do + %Operation{ + tags: ["admin", "chat"], + summary: "Get the most recent messages of the chat", + operationId: "AdminAPI.ChatController.messages", + parameters: + [Operation.parameter(:id, :path, :string, "The ID of the Chat")] ++ + pagination_params(), + responses: %{ + 200 => + Operation.response( + "The messages in the chat", + "application/json", + Pleroma.Web.ApiSpec.ChatOperation.chat_messages_response() + ) + }, + security: [ + %{ + "oAuth" => ["read:chats"] + } + ] + } + end + + def show_operation do + %Operation{ + tags: ["chat"], + summary: "Create a chat", + operationId: "AdminAPI.ChatController.show", + parameters: [ + Operation.parameter( + :id, + :path, + :string, + "The id of the chat", + required: true, + example: "1234" + ) + ], + responses: %{ + 200 => + Operation.response( + "The existing chat", + "application/json", + Chat + ) + }, + security: [ + %{ + "oAuth" => ["read"] + } + ] + } + end +end diff --git a/lib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex b/lib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex @@ -0,0 +1,115 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.Helpers + alias Pleroma.Web.ApiSpec.Schemas.ApiError + + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def show_operation do + %Operation{ + tags: ["Admin", "InstanceDocument"], + summary: "Get the instance document", + operationId: "AdminAPI.InstanceDocumentController.show", + security: [%{"oAuth" => ["read"]}], + parameters: [ + Operation.parameter(:name, :path, %Schema{type: :string}, "The document name", + required: true + ) + | Helpers.admin_api_params() + ], + responses: %{ + 200 => document_content(), + 400 => Operation.response("Bad Request", "application/json", ApiError), + 403 => Operation.response("Forbidden", "application/json", ApiError), + 404 => Operation.response("Not Found", "application/json", ApiError) + } + } + end + + def update_operation do + %Operation{ + tags: ["Admin", "InstanceDocument"], + summary: "Update the instance document", + operationId: "AdminAPI.InstanceDocumentController.update", + security: [%{"oAuth" => ["write"]}], + requestBody: Helpers.request_body("Parameters", update_request()), + parameters: [ + Operation.parameter(:name, :path, %Schema{type: :string}, "The document name", + required: true + ) + | Helpers.admin_api_params() + ], + responses: %{ + 200 => Operation.response("InstanceDocument", "application/json", instance_document()), + 400 => Operation.response("Bad Request", "application/json", ApiError), + 403 => Operation.response("Forbidden", "application/json", ApiError), + 404 => Operation.response("Not Found", "application/json", ApiError) + } + } + end + + defp update_request do + %Schema{ + title: "UpdateRequest", + description: "POST body for uploading the file", + type: :object, + required: [:file], + properties: %{ + file: %Schema{ + type: :string, + format: :binary, + description: "The file to be uploaded, using multipart form data." + } + } + } + end + + def delete_operation do + %Operation{ + tags: ["Admin", "InstanceDocument"], + summary: "Get the instance document", + operationId: "AdminAPI.InstanceDocumentController.delete", + security: [%{"oAuth" => ["write"]}], + parameters: [ + Operation.parameter(:name, :path, %Schema{type: :string}, "The document name", + required: true + ) + | Helpers.admin_api_params() + ], + responses: %{ + 200 => Operation.response("InstanceDocument", "application/json", instance_document()), + 400 => Operation.response("Bad Request", "application/json", ApiError), + 403 => Operation.response("Forbidden", "application/json", ApiError), + 404 => Operation.response("Not Found", "application/json", ApiError) + } + } + end + + defp instance_document do + %Schema{ + title: "InstanceDocument", + type: :object, + properties: %{ + url: %Schema{type: :string} + }, + example: %{ + "url" => "https://example.com/static/terms-of-service.html" + } + } + end + + defp document_content do + Operation.response("InstanceDocumentContent", "text/html", %Schema{ + type: :string, + example: "<h1>Instance panel</h1>" + }) + end +end diff --git a/lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex b/lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex @@ -69,7 +69,7 @@ defmodule Pleroma.Web.ApiSpec.CustomEmojiOperation do type: :object, properties: %{ category: %Schema{type: :string}, - tags: %Schema{type: :array} + tags: %Schema{type: :array, items: %Schema{type: :string}} } } ], diff --git a/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex b/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex @@ -23,7 +23,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do parameters: [ Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), Operation.parameter(:emoji, :path, :string, "Filter by a single unicode emoji", - required: false + required: nil ) ], security: [%{"oAuth" => ["read:statuses"]}], diff --git a/lib/pleroma/web/api_spec/operations/list_operation.ex b/lib/pleroma/web/api_spec/operations/list_operation.ex @@ -114,7 +114,7 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do description: "Add accounts to the given list.", operationId: "ListController.add_to_list", parameters: [id_param()], - requestBody: add_remove_accounts_request(), + requestBody: add_remove_accounts_request(true), security: [%{"oAuth" => ["write:lists"]}], responses: %{ 200 => Operation.response("Empty object", "application/json", %Schema{type: :object}) @@ -127,8 +127,16 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do tags: ["Lists"], summary: "Remove accounts from list", operationId: "ListController.remove_from_list", - parameters: [id_param()], - requestBody: add_remove_accounts_request(), + parameters: [ + id_param(), + Operation.parameter( + :account_ids, + :query, + %Schema{type: :array, items: %Schema{type: :string}}, + "Array of account IDs" + ) + ], + requestBody: add_remove_accounts_request(false), security: [%{"oAuth" => ["write:lists"]}], responses: %{ 200 => Operation.response("Empty object", "application/json", %Schema{type: :object}) @@ -171,7 +179,7 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do ) end - defp add_remove_accounts_request do + defp add_remove_accounts_request(required) when is_boolean(required) do request_body( "Parameters", %Schema{ @@ -179,10 +187,9 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do type: :object, properties: %{ account_ids: %Schema{type: :array, description: "Array of account IDs", items: FlakeID} - }, - required: [:account_ids] + } }, - required: true + required: required ) end end diff --git a/lib/pleroma/web/api_spec/operations/user_import_operation.ex b/lib/pleroma/web/api_spec/operations/user_import_operation.ex @@ -0,0 +1,80 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.UserImportOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.Schemas.ApiError + + import Pleroma.Web.ApiSpec.Helpers + + @spec open_api_operation(atom) :: Operation.t() + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def follow_operation do + %Operation{ + tags: ["follow_import"], + summary: "Imports your follows.", + operationId: "UserImportController.follow", + requestBody: request_body("Parameters", import_request(), required: true), + responses: %{ + 200 => ok_response(), + 500 => Operation.response("Error", "application/json", ApiError) + }, + security: [%{"oAuth" => ["write:follow"]}] + } + end + + def blocks_operation do + %Operation{ + tags: ["blocks_import"], + summary: "Imports your blocks.", + operationId: "UserImportController.blocks", + requestBody: request_body("Parameters", import_request(), required: true), + responses: %{ + 200 => ok_response(), + 500 => Operation.response("Error", "application/json", ApiError) + }, + security: [%{"oAuth" => ["write:blocks"]}] + } + end + + def mutes_operation do + %Operation{ + tags: ["mutes_import"], + summary: "Imports your mutes.", + operationId: "UserImportController.mutes", + requestBody: request_body("Parameters", import_request(), required: true), + responses: %{ + 200 => ok_response(), + 500 => Operation.response("Error", "application/json", ApiError) + }, + security: [%{"oAuth" => ["write:mutes"]}] + } + end + + defp import_request do + %Schema{ + type: :object, + required: [:list], + properties: %{ + list: %Schema{ + description: + "STRING or FILE containing a whitespace-separated list of accounts to import.", + anyOf: [ + %Schema{type: :string, format: :binary}, + %Schema{type: :string} + ] + } + } + } + end + + defp ok_response do + Operation.response("Ok", "application/json", %Schema{type: :string, example: "ok"}) + end +end diff --git a/lib/pleroma/web/api_spec/schemas/chat_message.ex b/lib/pleroma/web/api_spec/schemas/chat_message.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.Schemas.Emoji require OpenApiSpex @@ -18,7 +19,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do chat_id: %Schema{type: :string}, content: %Schema{type: :string, nullable: true}, created_at: %Schema{type: :string, format: :"date-time"}, - emojis: %Schema{type: :array}, + emojis: %Schema{type: :array, items: Emoji}, attachment: %Schema{type: :object, nullable: true}, card: %Schema{ type: :object, diff --git a/lib/pleroma/web/api_spec/schemas/scheduled_status.ex b/lib/pleroma/web/api_spec/schemas/scheduled_status.ex @@ -27,9 +27,9 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ScheduledStatus do media_ids: %Schema{type: :array, nullable: true, items: %Schema{type: :string}}, sensitive: %Schema{type: :boolean, nullable: true}, spoiler_text: %Schema{type: :string, nullable: true}, - visibility: %Schema{type: VisibilityScope, nullable: true}, + visibility: %Schema{allOf: [VisibilityScope], nullable: true}, scheduled_at: %Schema{type: :string, format: :"date-time", nullable: true}, - poll: %Schema{type: Poll, nullable: true}, + poll: %Schema{allOf: [Poll], nullable: true}, in_reply_to_id: %Schema{type: :string, nullable: true} } } diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex @@ -68,7 +68,7 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do nickname = value([registration_attrs["nickname"], Registration.nickname(registration)]) email = value([registration_attrs["email"], Registration.email(registration)]) name = value([registration_attrs["name"], Registration.name(registration)]) || nickname - bio = value([registration_attrs["bio"], Registration.description(registration)]) + bio = value([registration_attrs["bio"], Registration.description(registration)]) || "" random_password = :crypto.strong_rand_bytes(64) |> Base.encode64() diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex @@ -202,7 +202,7 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do additional = case draft.expires_at do - %NaiveDateTime{} = expires_at -> Map.put(additional, "expires_at", expires_at) + %DateTime{} = expires_at -> Map.put(additional, "expires_at", expires_at) _ -> additional end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex @@ -4,7 +4,6 @@ defmodule Pleroma.Web.CommonAPI do alias Pleroma.Activity - alias Pleroma.ActivityExpiration alias Pleroma.Conversation.Participation alias Pleroma.Formatter alias Pleroma.Object @@ -384,9 +383,9 @@ defmodule Pleroma.Web.CommonAPI do def check_expiry_date({:ok, nil} = res), do: res def check_expiry_date({:ok, in_seconds}) do - expiry = NaiveDateTime.utc_now() |> NaiveDateTime.add(in_seconds) + expiry = DateTime.add(DateTime.utc_now(), in_seconds) - if ActivityExpiration.expires_late_enough?(expiry) do + if Pleroma.Workers.PurgeExpiredActivity.expires_late_enough?(expiry) do {:ok, expiry} else {:error, "Expiry date is too soon"} @@ -455,7 +454,8 @@ defmodule Pleroma.Web.CommonAPI do end def add_mute(user, activity) do - with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]) do + with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]), + _ <- Pleroma.Notification.mark_context_as_read(user, activity.data["context"]) do {:ok, activity} else {:error, _} -> {:error, dgettext("errors", "conversation is already muted")} @@ -553,4 +553,21 @@ defmodule Pleroma.Web.CommonAPI do def show_reblogs(%User{} = user, %User{} = target) do UserRelationship.delete_reblog_mute(user, target) end + + def get_user(ap_id, fake_record_fallback \\ true) do + cond do + user = User.get_cached_by_ap_id(ap_id) -> + user + + user = User.get_by_guessed_nickname(ap_id) -> + user + + fake_record_fallback -> + # TODO: refactor (fake records is never a good idea) + User.error_user(ap_id) + + true -> + nil + end + end end diff --git a/lib/pleroma/web/fed_sockets/fed_registry.ex b/lib/pleroma/web/fed_sockets/fed_registry.ex @@ -0,0 +1,185 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.FedRegistry do + @moduledoc """ + The FedRegistry stores the active FedSockets for quick retrieval. + + The storage and retrieval portion of the FedRegistry is done in process through + elixir's `Registry` module for speed and its ability to monitor for terminated processes. + + Dropped connections will be caught by `Registry` and deleted. Since the next + message will initiate a new connection there is no reason to try and reconnect at that point. + + Normally outside modules should have no need to call or use the FedRegistry themselves. + """ + + alias Pleroma.Web.FedSockets.FedSocket + alias Pleroma.Web.FedSockets.SocketInfo + + require Logger + + @default_rejection_duration 15 * 60 * 1000 + @rejections :fed_socket_rejections + + @doc """ + Retrieves a FedSocket from the Registry given it's origin. + + The origin is expected to be a string identifying the endpoint "example.com" or "example2.com:8080" + + Will return: + * {:ok, fed_socket} for working FedSockets + * {:error, :rejected} for origins that have been tried and refused within the rejection duration interval + * {:error, some_reason} usually :missing for unknown origins + """ + def get_fed_socket(origin) do + case get_registry_data(origin) do + {:error, reason} -> + {:error, reason} + + {:ok, %{state: :connected} = socket_info} -> + {:ok, socket_info} + end + end + + @doc """ + Adds a connected FedSocket to the Registry. + + Always returns {:ok, fed_socket} + """ + def add_fed_socket(origin, pid \\ nil) do + origin + |> SocketInfo.build(pid) + |> SocketInfo.connect() + |> add_socket_info + end + + defp add_socket_info(%{origin: origin, state: :connected} = socket_info) do + case Registry.register(FedSockets.Registry, origin, socket_info) do + {:ok, _owner} -> + clear_prior_rejection(origin) + Logger.debug("fedsocket added: #{inspect(origin)}") + + {:ok, socket_info} + + {:error, {:already_registered, _pid}} -> + FedSocket.close(socket_info) + existing_socket_info = Registry.lookup(FedSockets.Registry, origin) + + {:ok, existing_socket_info} + + _ -> + {:error, :error_adding_socket} + end + end + + @doc """ + Mark this origin as having rejected a connection attempt. + This will keep it from getting additional connection attempts + for a period of time specified in the config. + + Always returns {:ok, new_reg_data} + """ + def set_host_rejected(uri) do + new_reg_data = + uri + |> SocketInfo.origin() + |> get_or_create_registry_data() + |> set_to_rejected() + |> save_registry_data() + + {:ok, new_reg_data} + end + + @doc """ + Retrieves the FedRegistryData from the Registry given it's origin. + + The origin is expected to be a string identifying the endpoint "example.com" or "example2.com:8080" + + Will return: + * {:ok, fed_registry_data} for known origins + * {:error, :missing} for uniknown origins + * {:error, :cache_error} indicating some low level runtime issues + """ + def get_registry_data(origin) do + case Registry.lookup(FedSockets.Registry, origin) do + [] -> + if is_rejected?(origin) do + Logger.debug("previously rejected fedsocket requested") + {:error, :rejected} + else + {:error, :missing} + end + + [{_pid, %{state: :connected} = socket_info}] -> + {:ok, socket_info} + + _ -> + {:error, :cache_error} + end + end + + @doc """ + Retrieves a map of all sockets from the Registry. The keys are the origins and the values are the corresponding SocketInfo + """ + def list_all do + (list_all_connected() ++ list_all_rejected()) + |> Enum.into(%{}) + end + + defp list_all_connected do + FedSockets.Registry + |> Registry.select([{{:"$1", :_, :"$3"}, [], [{{:"$1", :"$3"}}]}]) + end + + defp list_all_rejected do + {:ok, keys} = Cachex.keys(@rejections) + + {:ok, registry_data} = + Cachex.execute(@rejections, fn worker -> + Enum.map(keys, fn k -> {k, Cachex.get!(worker, k)} end) + end) + + registry_data + end + + defp clear_prior_rejection(origin), + do: Cachex.del(@rejections, origin) + + defp is_rejected?(origin) do + case Cachex.get(@rejections, origin) do + {:ok, nil} -> + false + + {:ok, _} -> + true + end + end + + defp get_or_create_registry_data(origin) do + case get_registry_data(origin) do + {:error, :missing} -> + %SocketInfo{origin: origin} + + {:ok, socket_info} -> + socket_info + end + end + + defp save_registry_data(%SocketInfo{origin: origin, state: :connected} = socket_info) do + {:ok, true} = Registry.update_value(FedSockets.Registry, origin, fn _ -> socket_info end) + socket_info + end + + defp save_registry_data(%SocketInfo{origin: origin, state: :rejected} = socket_info) do + rejection_expiration = + Pleroma.Config.get([:fed_sockets, :rejection_duration], @default_rejection_duration) + + {:ok, true} = Cachex.put(@rejections, origin, socket_info, ttl: rejection_expiration) + socket_info + end + + defp set_to_rejected(%SocketInfo{} = socket_info), + do: %SocketInfo{socket_info | state: :rejected} +end diff --git a/lib/pleroma/web/fed_sockets/fed_socket.ex b/lib/pleroma/web/fed_sockets/fed_socket.ex @@ -0,0 +1,137 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.FedSocket do + @moduledoc """ + The FedSocket module abstracts the actions to be taken taken on connections regardless of + whether the connection started as inbound or outbound. + + + Normally outside modules will have no need to call the FedSocket module directly. + """ + + alias Pleroma.Object + alias Pleroma.Object.Containment + alias Pleroma.User + alias Pleroma.Web.ActivityPub.ObjectView + alias Pleroma.Web.ActivityPub.UserView + alias Pleroma.Web.ActivityPub.Visibility + alias Pleroma.Web.FedSockets.FetchRegistry + alias Pleroma.Web.FedSockets.IngesterWorker + alias Pleroma.Web.FedSockets.OutgoingHandler + alias Pleroma.Web.FedSockets.SocketInfo + + require Logger + + @shake "61dd18f7-f1e6-49a4-939a-a749fcdc1103" + + def connect_to_host(uri) do + case OutgoingHandler.start_link(uri) do + {:ok, pid} -> + {:ok, pid} + + error -> + {:error, error} + end + end + + def close(%SocketInfo{pid: socket_pid}), + do: Process.send(socket_pid, :close, []) + + def publish(%SocketInfo{pid: socket_pid}, json) do + %{action: :publish, data: json} + |> Jason.encode!() + |> send_packet(socket_pid) + end + + def fetch(%SocketInfo{pid: socket_pid}, id) do + fetch_uuid = FetchRegistry.register_fetch(id) + + %{action: :fetch, data: id, uuid: fetch_uuid} + |> Jason.encode!() + |> send_packet(socket_pid) + + wait_for_fetch_to_return(fetch_uuid, 0) + end + + def receive_package(%SocketInfo{} = fed_socket, json) do + json + |> Jason.decode!() + |> process_package(fed_socket) + end + + defp wait_for_fetch_to_return(uuid, cntr) do + case FetchRegistry.check_fetch(uuid) do + {:error, :waiting} -> + Process.sleep(:math.pow(cntr, 3) |> Kernel.trunc()) + wait_for_fetch_to_return(uuid, cntr + 1) + + {:error, :missing} -> + Logger.error("FedSocket fetch timed out - #{inspect(uuid)}") + {:error, :timeout} + + {:ok, _fr} -> + FetchRegistry.pop_fetch(uuid) + end + end + + defp process_package(%{"action" => "publish", "data" => data}, %{origin: origin} = _fed_socket) do + if Containment.contain_origin(origin, data) do + IngesterWorker.enqueue("ingest", %{"object" => data}) + end + + {:reply, %{"action" => "publish_reply", "status" => "processed"}} + end + + defp process_package(%{"action" => "fetch_reply", "uuid" => uuid, "data" => data}, _fed_socket) do + FetchRegistry.register_fetch_received(uuid, data) + {:noreply, nil} + end + + defp process_package(%{"action" => "fetch", "uuid" => uuid, "data" => ap_id}, _fed_socket) do + {:ok, data} = render_fetched_data(ap_id, uuid) + {:reply, data} + end + + defp process_package(%{"action" => "publish_reply"}, _fed_socket) do + {:noreply, nil} + end + + defp process_package(other, _fed_socket) do + Logger.warn("unknown json packages received #{inspect(other)}") + {:noreply, nil} + end + + defp render_fetched_data(ap_id, uuid) do + {:ok, + %{ + "action" => "fetch_reply", + "status" => "processed", + "uuid" => uuid, + "data" => represent_item(ap_id) + }} + end + + defp represent_item(ap_id) do + case User.get_by_ap_id(ap_id) do + nil -> + object = Object.get_cached_by_ap_id(ap_id) + + if Visibility.is_public?(object) do + Phoenix.View.render_to_string(ObjectView, "object.json", object: object) + else + nil + end + + user -> + Phoenix.View.render_to_string(UserView, "user.json", user: user) + end + end + + defp send_packet(data, socket_pid) do + Process.send(socket_pid, {:send, data}, []) + end + + def shake, do: @shake +end diff --git a/lib/pleroma/web/fed_sockets/fed_sockets.ex b/lib/pleroma/web/fed_sockets/fed_sockets.ex @@ -0,0 +1,185 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets do + @moduledoc """ + This documents the FedSockets framework. A framework for federating + ActivityPub objects between servers via persistant WebSocket connections. + + FedSockets allow servers to authenticate on first contact and maintain that + connection, eliminating the need to authenticate every time data needs to be shared. + + ## Protocol + FedSockets currently support 2 types of data transfer: + * `publish` method which doesn't require a response + * `fetch` method requires a response be sent + + ### Publish + The publish operation sends a json encoded map of the shape: + %{action: :publish, data: json} + and accepts (but does not require) a reply of form: + %{"action" => "publish_reply"} + + The outgoing params represent + * data: ActivityPub object encoded into json + + + ### Fetch + The fetch operation sends a json encoded map of the shape: + %{action: :fetch, data: id, uuid: fetch_uuid} + and requires a reply of form: + %{"action" => "fetch_reply", "uuid" => uuid, "data" => data} + + The outgoing params represent + * id: an ActivityPub object URI + * uuid: a unique uuid generated by the sender + + The reply params represent + * data: an ActivityPub object encoded into json + * uuid: the uuid sent along with the fetch request + + ## Examples + Clients of FedSocket transfers shouldn't need to use any of the functions outside of this module. + + A typical publish operation can be performed through the following code, and a fetch operation in a similar manner. + + case FedSockets.get_or_create_fed_socket(inbox) do + {:ok, fedsocket} -> + FedSockets.publish(fedsocket, json) + + _ -> + alternative_publish(inbox, actor, json, params) + end + + ## Configuration + FedSockets have the following config settings + + config :pleroma, :fed_sockets, + enabled: true, + ping_interval: :timer.seconds(15), + connection_duration: :timer.hours(1), + rejection_duration: :timer.hours(1), + fed_socket_fetches: [ + default: 12_000, + interval: 3_000, + lazy: false + ] + * enabled - turn FedSockets on or off with this flag. Can be toggled at runtime. + * connection_duration - How long a FedSocket can sit idle before it's culled. + * rejection_duration - After failing to make a FedSocket connection a host will be excluded + from further connections for this amount of time + * fed_socket_fetches - Use these parameters to pass options to the Cachex queue backing the FetchRegistry + * fed_socket_rejections - Use these parameters to pass options to the Cachex queue backing the FedRegistry + + Cachex options are + * default: the minimum amount of time a fetch can wait before it times out. + * interval: the interval between checks for timed out entries. This plus the default represent the maximum time allowed + * lazy: leave at false for consistant and fast lookups, set to true for stricter timeout enforcement + + """ + require Logger + + alias Pleroma.Web.FedSockets.FedRegistry + alias Pleroma.Web.FedSockets.FedSocket + alias Pleroma.Web.FedSockets.SocketInfo + + @doc """ + returns a FedSocket for the given origin. Will reuse an existing one or create a new one. + + address is expected to be a fully formed URL such as: + "http://www.example.com" or "http://www.example.com:8080" + + It can and usually does include additional path parameters, + but these are ignored as the FedSockets are organized by host and port info alone. + """ + def get_or_create_fed_socket(address) do + with {:cache, {:error, :missing}} <- {:cache, get_fed_socket(address)}, + {:connect, {:ok, _pid}} <- {:connect, FedSocket.connect_to_host(address)}, + {:cache, {:ok, fed_socket}} <- {:cache, get_fed_socket(address)} do + Logger.debug("fedsocket created for - #{inspect(address)}") + {:ok, fed_socket} + else + {:cache, {:ok, socket}} -> + Logger.debug("fedsocket found in cache - #{inspect(address)}") + {:ok, socket} + + {:cache, {:error, :rejected} = e} -> + e + + {:connect, {:error, _host}} -> + Logger.debug("set host rejected for - #{inspect(address)}") + FedRegistry.set_host_rejected(address) + {:error, :rejected} + + {_, {:error, :disabled}} -> + {:error, :disabled} + + {_, {:error, reason}} -> + Logger.warn("get_or_create_fed_socket error - #{inspect(reason)}") + {:error, reason} + end + end + + @doc """ + returns a FedSocket for the given origin. Will not create a new FedSocket if one does not exist. + + address is expected to be a fully formed URL such as: + "http://www.example.com" or "http://www.example.com:8080" + """ + def get_fed_socket(address) do + origin = SocketInfo.origin(address) + + with {:config, true} <- {:config, Pleroma.Config.get([:fed_sockets, :enabled], false)}, + {:ok, socket} <- FedRegistry.get_fed_socket(origin) do + {:ok, socket} + else + {:config, _} -> + {:error, :disabled} + + {:error, :rejected} -> + Logger.debug("FedSocket previously rejected - #{inspect(origin)}") + {:error, :rejected} + + {:error, reason} -> + {:error, reason} + end + end + + @doc """ + Sends the supplied data via the publish protocol. + It will not block waiting for a reply. + Returns :ok but this is not an indication of a successful transfer. + + the data is expected to be JSON encoded binary data. + """ + def publish(%SocketInfo{} = fed_socket, json) do + FedSocket.publish(fed_socket, json) + end + + @doc """ + Sends the supplied data via the fetch protocol. + It will block waiting for a reply or timeout. + + Returns {:ok, object} where object is the requested object (or nil) + {:error, :timeout} in the event the message was not responded to + + the id is expected to be the URI of an ActivityPub object. + """ + def fetch(%SocketInfo{} = fed_socket, id) do + FedSocket.fetch(fed_socket, id) + end + + @doc """ + Disconnect all and restart FedSockets. + This is mainly used in development and testing but could be useful in production. + """ + def reset do + FedRegistry + |> Process.whereis() + |> Process.exit(:testing) + end + + def uri_for_origin(origin), + do: "ws://#{origin}/api/fedsocket/v1" +end diff --git a/lib/pleroma/web/fed_sockets/fetch_registry.ex b/lib/pleroma/web/fed_sockets/fetch_registry.ex @@ -0,0 +1,151 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.FetchRegistry do + @moduledoc """ + The FetchRegistry acts as a broker for fetch requests and return values. + This allows calling processes to block while waiting for a reply. + It doesn't impose it's own process instead using `Cachex` to handle fetches in process, allowing + multi threaded processes to avoid bottlenecking. + + Normally outside modules will have no need to call or use the FetchRegistry themselves. + + The `Cachex` parameters can be controlled from the config. Since exact timeout intervals + aren't necessary the following settings are used by default: + + config :pleroma, :fed_sockets, + fed_socket_fetches: [ + default: 12_000, + interval: 3_000, + lazy: false + ] + + """ + + defmodule FetchRegistryData do + defstruct uuid: nil, + sent_json: nil, + received_json: nil, + sent_at: nil, + received_at: nil + end + + alias Ecto.UUID + + require Logger + + @fetches :fed_socket_fetches + + @doc """ + Registers a json request wth the FetchRegistry and returns the identifying UUID. + """ + def register_fetch(json) do + %FetchRegistryData{uuid: uuid} = + json + |> new_registry_data + |> save_registry_data + + uuid + end + + @doc """ + Reports on the status of a Fetch given the identifying UUID. + + Will return + * {:ok, fetched_object} if a fetch has completed + * {:error, :waiting} if a fetch is still pending + * {:error, other_error} usually :missing to indicate a fetch that has timed out + """ + def check_fetch(uuid) do + case get_registry_data(uuid) do + {:ok, %FetchRegistryData{received_at: nil}} -> + {:error, :waiting} + + {:ok, %FetchRegistryData{} = reg_data} -> + {:ok, reg_data} + + e -> + e + end + end + + @doc """ + Retrieves the response to a fetch given the identifying UUID. + The completed fetch will be deleted from the FetchRegistry + + Will return + * {:ok, fetched_object} if a fetch has completed + * {:error, :waiting} if a fetch is still pending + * {:error, other_error} usually :missing to indicate a fetch that has timed out + """ + def pop_fetch(uuid) do + case check_fetch(uuid) do + {:ok, %FetchRegistryData{received_json: received_json}} -> + delete_registry_data(uuid) + {:ok, received_json} + + e -> + e + end + end + + @doc """ + This is called to register a fetch has returned. + It expects the result data along with the UUID that was sent in the request + + Will return the fetched object or :error + """ + def register_fetch_received(uuid, data) do + case get_registry_data(uuid) do + {:ok, %FetchRegistryData{received_at: nil} = reg_data} -> + reg_data + |> set_fetch_received(data) + |> save_registry_data() + + {:ok, %FetchRegistryData{} = reg_data} -> + Logger.warn("tried to add fetched data twice - #{uuid}") + reg_data + + {:error, _} -> + Logger.warn("Error adding fetch to registry - #{uuid}") + :error + end + end + + defp new_registry_data(json) do + %FetchRegistryData{ + uuid: UUID.generate(), + sent_json: json, + sent_at: :erlang.monotonic_time(:millisecond) + } + end + + defp get_registry_data(origin) do + case Cachex.get(@fetches, origin) do + {:ok, nil} -> + {:error, :missing} + + {:ok, reg_data} -> + {:ok, reg_data} + + _ -> + {:error, :cache_error} + end + end + + defp set_fetch_received(%FetchRegistryData{} = reg_data, data), + do: %FetchRegistryData{ + reg_data + | received_at: :erlang.monotonic_time(:millisecond), + received_json: data + } + + defp save_registry_data(%FetchRegistryData{uuid: uuid} = reg_data) do + {:ok, true} = Cachex.put(@fetches, uuid, reg_data) + reg_data + end + + defp delete_registry_data(origin), + do: {:ok, true} = Cachex.del(@fetches, origin) +end diff --git a/lib/pleroma/web/fed_sockets/incoming_handler.ex b/lib/pleroma/web/fed_sockets/incoming_handler.ex @@ -0,0 +1,88 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.IncomingHandler do + require Logger + + alias Pleroma.Web.FedSockets.FedRegistry + alias Pleroma.Web.FedSockets.FedSocket + alias Pleroma.Web.FedSockets.SocketInfo + + import HTTPSignatures, only: [validate_conn: 1, split_signature: 1] + + @behaviour :cowboy_websocket + + def init(req, state) do + shake = FedSocket.shake() + + with true <- Pleroma.Config.get([:fed_sockets, :enabled]), + sec_protocol <- :cowboy_req.header("sec-websocket-protocol", req, nil), + headers = %{"(request-target)" => ^shake} <- :cowboy_req.headers(req), + true <- validate_conn(%{req_headers: headers}), + %{"keyId" => origin} <- split_signature(headers["signature"]) do + req = + if is_nil(sec_protocol) do + req + else + :cowboy_req.set_resp_header("sec-websocket-protocol", sec_protocol, req) + end + + {:cowboy_websocket, req, %{origin: origin}, %{}} + else + _ -> + {:ok, req, state} + end + end + + def websocket_init(%{origin: origin}) do + case FedRegistry.add_fed_socket(origin) do + {:ok, socket_info} -> + {:ok, socket_info} + + e -> + Logger.error("FedSocket websocket_init failed - #{inspect(e)}") + {:error, inspect(e)} + end + end + + # Use the ping to check if the connection should be expired + def websocket_handle(:ping, socket_info) do + if SocketInfo.expired?(socket_info) do + {:stop, socket_info} + else + {:ok, socket_info, :hibernate} + end + end + + def websocket_handle({:text, data}, socket_info) do + socket_info = SocketInfo.touch(socket_info) + + case FedSocket.receive_package(socket_info, data) do + {:noreply, _} -> + {:ok, socket_info} + + {:reply, reply} -> + {:reply, {:text, Jason.encode!(reply)}, socket_info} + + {:error, reason} -> + Logger.error("incoming error - receive_package: #{inspect(reason)}") + {:ok, socket_info} + end + end + + def websocket_info({:send, message}, socket_info) do + socket_info = SocketInfo.touch(socket_info) + + {:reply, {:text, message}, socket_info} + end + + def websocket_info(:close, state) do + {:stop, state} + end + + def websocket_info(message, state) do + Logger.debug("#{__MODULE__} unknown message #{inspect(message)}") + {:ok, state} + end +end diff --git a/lib/pleroma/web/fed_sockets/ingester_worker.ex b/lib/pleroma/web/fed_sockets/ingester_worker.ex @@ -0,0 +1,33 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.IngesterWorker do + use Pleroma.Workers.WorkerHelper, queue: "ingestion_queue" + require Logger + + alias Pleroma.Web.Federator + + @impl Oban.Worker + def perform(%Job{args: %{"op" => "ingest", "object" => ingestee}}) do + try do + ingestee + |> Jason.decode!() + |> do_ingestion() + rescue + e -> + Logger.error("IngesterWorker error - #{inspect(e)}") + e + end + end + + defp do_ingestion(params) do + case Federator.incoming_ap_doc(params) do + {:error, reason} -> + {:error, reason} + + {:ok, object} -> + {:ok, object} + end + end +end diff --git a/lib/pleroma/web/fed_sockets/outgoing_handler.ex b/lib/pleroma/web/fed_sockets/outgoing_handler.ex @@ -0,0 +1,151 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.OutgoingHandler do + use GenServer + + require Logger + + alias Pleroma.Application + alias Pleroma.Web.ActivityPub.InternalFetchActor + alias Pleroma.Web.FedSockets + alias Pleroma.Web.FedSockets.FedRegistry + alias Pleroma.Web.FedSockets.FedSocket + alias Pleroma.Web.FedSockets.SocketInfo + + def start_link(uri) do + GenServer.start_link(__MODULE__, %{uri: uri}) + end + + def init(%{uri: uri}) do + case initiate_connection(uri) do + {:ok, ws_origin, conn_pid} -> + FedRegistry.add_fed_socket(ws_origin, conn_pid) + + {:error, reason} -> + Logger.debug("Outgoing connection failed - #{inspect(reason)}") + :ignore + end + end + + def handle_info({:gun_ws, conn_pid, _ref, {:text, data}}, socket_info) do + socket_info = SocketInfo.touch(socket_info) + + case FedSocket.receive_package(socket_info, data) do + {:noreply, _} -> + {:noreply, socket_info} + + {:reply, reply} -> + :gun.ws_send(conn_pid, {:text, Jason.encode!(reply)}) + {:noreply, socket_info} + + {:error, reason} -> + Logger.error("incoming error - receive_package: #{inspect(reason)}") + {:noreply, socket_info} + end + end + + def handle_info(:close, state) do + Logger.debug("Sending close frame !!!!!!!") + {:close, state} + end + + def handle_info({:gun_down, _pid, _prot, :closed, _}, state) do + {:stop, :normal, state} + end + + def handle_info({:send, data}, %{conn_pid: conn_pid} = socket_info) do + socket_info = SocketInfo.touch(socket_info) + :gun.ws_send(conn_pid, {:text, data}) + {:noreply, socket_info} + end + + def handle_info({:gun_ws, _, _, :pong}, state) do + {:noreply, state, :hibernate} + end + + def handle_info(msg, state) do + Logger.debug("#{__MODULE__} unhandled event #{inspect(msg)}") + {:noreply, state} + end + + def terminate(reason, state) do + Logger.debug( + "#{__MODULE__} terminating outgoing connection for #{inspect(state)} for #{inspect(reason)}" + ) + + {:ok, state} + end + + def initiate_connection(uri) do + ws_uri = + uri + |> SocketInfo.origin() + |> FedSockets.uri_for_origin() + + %{host: host, port: port, path: path} = URI.parse(ws_uri) + + with {:ok, conn_pid} <- :gun.open(to_charlist(host), port, %{protocols: [:http]}), + {:ok, _} <- :gun.await_up(conn_pid), + reference <- + :gun.get(conn_pid, to_charlist(path), [ + {'user-agent', to_charlist(Application.user_agent())} + ]), + {:response, :fin, 204, _} <- :gun.await(conn_pid, reference), + headers <- build_headers(uri), + ref <- :gun.ws_upgrade(conn_pid, to_charlist(path), headers, %{silence_pings: false}) do + receive do + {:gun_upgrade, ^conn_pid, ^ref, [<<"websocket">>], _} -> + {:ok, ws_uri, conn_pid} + after + 15_000 -> + Logger.debug("Fedsocket timeout connecting to #{inspect(uri)}") + {:error, :timeout} + end + else + {:response, :nofin, 404, _} -> + {:error, :fedsockets_not_supported} + + e -> + Logger.debug("Fedsocket error connecting to #{inspect(uri)}") + {:error, e} + end + end + + defp build_headers(uri) do + host_for_sig = uri |> URI.parse() |> host_signature() + + shake = FedSocket.shake() + digest = "SHA-256=" <> (:crypto.hash(:sha256, shake) |> Base.encode64()) + date = Pleroma.Signature.signed_date() + shake_size = byte_size(shake) + + signature_opts = %{ + "(request-target)": shake, + "content-length": to_charlist("#{shake_size}"), + date: date, + digest: digest, + host: host_for_sig + } + + signature = Pleroma.Signature.sign(InternalFetchActor.get_actor(), signature_opts) + + [ + {'signature', to_charlist(signature)}, + {'date', date}, + {'digest', to_charlist(digest)}, + {'content-length', to_charlist("#{shake_size}")}, + {to_charlist("(request-target)"), to_charlist(shake)}, + {'user-agent', to_charlist(Application.user_agent())} + ] + end + + defp host_signature(%{host: host, scheme: scheme, port: port}) do + if port == URI.default_port(scheme) do + host + else + "#{host}:#{port}" + end + end +end diff --git a/lib/pleroma/web/fed_sockets/socket_info.ex b/lib/pleroma/web/fed_sockets/socket_info.ex @@ -0,0 +1,52 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.SocketInfo do + defstruct origin: nil, + pid: nil, + conn_pid: nil, + state: :default, + connected_until: nil + + alias Pleroma.Web.FedSockets.SocketInfo + @default_connection_duration 15 * 60 * 1000 + + def build(uri, conn_pid \\ nil) do + uri + |> build_origin() + |> build_pids(conn_pid) + |> touch() + end + + def touch(%SocketInfo{} = socket_info), + do: %{socket_info | connected_until: new_ttl()} + + def connect(%SocketInfo{} = socket_info), + do: %{socket_info | state: :connected} + + def expired?(%{connected_until: connected_until}), + do: connected_until < :erlang.monotonic_time(:millisecond) + + def origin(uri), + do: build_origin(uri).origin + + defp build_pids(socket_info, conn_pid), + do: struct(socket_info, pid: self(), conn_pid: conn_pid) + + defp build_origin(uri) when is_binary(uri), + do: uri |> URI.parse() |> build_origin + + defp build_origin(%{host: host, port: nil, scheme: scheme}), + do: build_origin(%{host: host, port: URI.default_port(scheme)}) + + defp build_origin(%{host: host, port: port}), + do: %SocketInfo{origin: "#{host}:#{port}"} + + defp new_ttl do + connection_duration = + Pleroma.Config.get([:fed_sockets, :connection_duration], @default_connection_duration) + + :erlang.monotonic_time(:millisecond) + connection_duration + end +end diff --git a/lib/pleroma/web/fed_sockets/supervisor.ex b/lib/pleroma/web/fed_sockets/supervisor.ex @@ -0,0 +1,59 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.Supervisor do + use Supervisor + import Cachex.Spec + + def start_link(opts) do + Supervisor.start_link(__MODULE__, opts, name: __MODULE__) + end + + def init(args) do + children = [ + build_cache(:fed_socket_fetches, args), + build_cache(:fed_socket_rejections, args), + {Registry, keys: :unique, name: FedSockets.Registry, meta: [rejected: %{}]} + ] + + opts = [strategy: :one_for_all, name: Pleroma.Web.Streamer.Supervisor] + Supervisor.init(children, opts) + end + + defp build_cache(name, args) do + opts = get_opts(name, args) + + %{ + id: String.to_atom("#{name}_cache"), + start: {Cachex, :start_link, [name, opts]}, + type: :worker + } + end + + defp get_opts(cache_name, args) + when cache_name in [:fed_socket_fetches, :fed_socket_rejections] do + default = get_opts_or_config(args, cache_name, :default, 15_000) + interval = get_opts_or_config(args, cache_name, :interval, 3_000) + lazy = get_opts_or_config(args, cache_name, :lazy, false) + + [expiration: expiration(default: default, interval: interval, lazy: lazy)] + end + + defp get_opts(name, args) do + Keyword.get(args, name, []) + end + + defp get_opts_or_config(args, name, key, default) do + args + |> Keyword.get(name, []) + |> Keyword.get(key) + |> case do + nil -> + Pleroma.Config.get([:fed_sockets, name, key], default) + + value -> + value + end + end +end diff --git a/lib/pleroma/web/federator/federator.ex b/lib/pleroma/web/federator/federator.ex @@ -66,14 +66,17 @@ defmodule Pleroma.Web.Federator do def perform(:incoming_ap_doc, params) do Logger.debug("Handling incoming AP activity") - params = Utils.normalize_params(params) + actor = + params + |> Map.get("actor") + |> Utils.get_ap_id() # NOTE: we use the actor ID to do the containment, this is fine because an # actor shouldn't be acting on objects outside their own AP server. - with {:ok, _user} <- ap_enabled_actor(params["actor"]), + with {_, {:ok, _user}} <- {:actor, ap_enabled_actor(actor)}, nil <- Activity.normalize(params["id"]), {_, :ok} <- - {:correct_origin?, Containment.contain_origin_from_id(params["actor"], params)}, + {:correct_origin?, Containment.contain_origin_from_id(actor, params)}, {:ok, activity} <- Transmogrifier.handle_incoming(params) do {:ok, activity} else @@ -85,10 +88,13 @@ defmodule Pleroma.Web.Federator do Logger.debug("Already had #{params["id"]}") {:error, :already_present} + {:actor, e} -> + Logger.debug("Unhandled actor #{actor}, #{inspect(e)}") + {:error, e} + e -> # Just drop those for now - Logger.debug("Unhandled activity") - Logger.debug(Jason.encode!(params, pretty: true)) + Logger.debug(fn -> "Unhandled activity\n" <> Jason.encode!(params, pretty: true) end) {:error, e} end end diff --git a/lib/pleroma/web/instance_document.ex b/lib/pleroma/web/instance_document.ex @@ -0,0 +1,62 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.InstanceDocument do + alias Pleroma.Config + alias Pleroma.Web.Endpoint + + @instance_documents %{ + "terms-of-service" => "/static/terms-of-service.html", + "instance-panel" => "/instance/panel.html" + } + + @spec get(String.t()) :: {:ok, String.t()} | {:error, atom()} + def get(document_name) do + case Map.fetch(@instance_documents, document_name) do + {:ok, path} -> {:ok, path} + _ -> {:error, :not_found} + end + end + + @spec put(String.t(), String.t()) :: {:ok, String.t()} | {:error, atom()} + def put(document_name, origin_path) do + with {_, {:ok, destination_path}} <- + {:instance_document, Map.fetch(@instance_documents, document_name)}, + :ok <- put_file(origin_path, destination_path) do + {:ok, Path.join(Endpoint.url(), destination_path)} + else + {:instance_document, :error} -> {:error, :not_found} + error -> error + end + end + + @spec delete(String.t()) :: :ok | {:error, atom()} + def delete(document_name) do + with {_, {:ok, path}} <- {:instance_document, Map.fetch(@instance_documents, document_name)}, + instance_static_dir_path <- instance_static_dir(path), + :ok <- File.rm(instance_static_dir_path) do + :ok + else + {:instance_document, :error} -> {:error, :not_found} + {:error, :enoent} -> {:error, :not_found} + error -> error + end + end + + defp put_file(origin_path, destination_path) do + with destination <- instance_static_dir(destination_path), + {_, :ok} <- {:mkdir_p, File.mkdir_p(Path.dirname(destination))}, + {_, {:ok, _}} <- {:copy, File.copy(origin_path, destination)} do + :ok + else + {error, _} -> {:error, error} + end + end + + defp instance_static_dir(filename) do + [:instance, :static_dir] + |> Config.get!() + |> Path.join(filename) + end +end diff --git a/lib/pleroma/web/mastodon_api/controllers/list_controller.ex b/lib/pleroma/web/mastodon_api/controllers/list_controller.ex @@ -74,7 +74,7 @@ defmodule Pleroma.Web.MastodonAPI.ListController do # DELETE /api/v1/lists/:id/accounts def remove_from_list( - %{assigns: %{list: list}, body_params: %{account_ids: account_ids}} = conn, + %{assigns: %{list: list}, params: %{account_ids: account_ids}} = conn, _ ) do Enum.each(account_ids, fn account_id -> @@ -86,6 +86,10 @@ defmodule Pleroma.Web.MastodonAPI.ListController do json(conn, %{}) end + def remove_from_list(%{body_params: params} = conn, _) do + remove_from_list(%{conn | params: params}, %{}) + end + defp list_by_id_and_user(%{assigns: %{user: user}, params: %{id: id}} = conn, _) do case Pleroma.List.get(id, user) do %Pleroma.List{} = list -> assign(conn, :list, list) diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -181,8 +181,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do user = User.sanitize_html(user, User.html_filter_policy(opts[:for])) display_name = user.name || user.nickname - image = User.avatar_url(user) |> MediaProxy.url() + avatar = User.avatar_url(user) |> MediaProxy.url() + avatar_static = User.avatar_url(user) |> MediaProxy.preview_url(static: true) header = User.banner_url(user) |> MediaProxy.url() + header_static = User.banner_url(user) |> MediaProxy.preview_url(static: true) following_count = if !user.hide_follows_count or !user.hide_follows or opts[:for] == user do @@ -245,12 +247,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do followers_count: followers_count, following_count: following_count, statuses_count: user.note_count, - note: user.bio || "", + note: user.bio, url: user.uri || user.ap_id, - avatar: image, - avatar_static: image, + avatar: avatar, + avatar_static: avatar_static, header: header, - header_static: header, + header_static: header_static, emojis: emojis, fields: user.fields, bot: bot, diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -8,7 +8,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do require Pleroma.Constants alias Pleroma.Activity - alias Pleroma.ActivityExpiration alias Pleroma.HTML alias Pleroma.Object alias Pleroma.Repo @@ -56,23 +55,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do end) end - def get_user(ap_id, fake_record_fallback \\ true) do - cond do - user = User.get_cached_by_ap_id(ap_id) -> - user - - user = User.get_by_guessed_nickname(ap_id) -> - user - - fake_record_fallback -> - # TODO: refactor (fake records is never a good idea) - User.error_user(ap_id) - - true -> - nil - end - end - defp get_context_id(%{data: %{"context_id" => context_id}}) when not is_nil(context_id), do: context_id @@ -120,7 +102,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do # Note: unresolved users are filtered out actors = (activities ++ parent_activities) - |> Enum.map(&get_user(&1.data["actor"], false)) + |> Enum.map(&CommonAPI.get_user(&1.data["actor"], false)) |> Enum.filter(& &1) UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes) @@ -139,7 +121,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do "show.json", %{activity: %{data: %{"type" => "Announce", "object" => _object}} = activity} = opts ) do - user = get_user(activity.data["actor"]) + user = CommonAPI.get_user(activity.data["actor"]) created_at = Utils.to_masto_date(activity.data["published"]) activity_object = Object.normalize(activity) @@ -212,7 +194,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do object = Object.normalize(activity) - user = get_user(activity.data["actor"]) + user = CommonAPI.get_user(activity.data["actor"]) user_follower_address = user.follower_address like_count = object.data["like_count"] || 0 @@ -245,8 +227,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do expires_at = with true <- client_posted_this_activity, - %ActivityExpiration{scheduled_at: scheduled_at} <- - ActivityExpiration.get_by_activity_id(activity.id) do + %Oban.Job{scheduled_at: scheduled_at} <- + Pleroma.Workers.PurgeExpiredActivity.get_expiration(activity.id) do scheduled_at else _ -> nil @@ -266,7 +248,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do reply_to = get_reply_to(activity, opts) - reply_to_user = reply_to && get_user(reply_to.data["actor"]) + reply_to_user = reply_to && CommonAPI.get_user(reply_to.data["actor"]) content = object @@ -433,6 +415,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do [attachment_url | _] = attachment["url"] media_type = attachment_url["mediaType"] || attachment_url["mimeType"] || "image" href = attachment_url["href"] |> MediaProxy.url() + href_preview = attachment_url["href"] |> MediaProxy.preview_url() type = cond do @@ -448,7 +431,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do id: to_string(attachment["id"] || hash_id), url: href, remote_url: href, - preview_url: href, + preview_url: href_preview, text_url: href, type: type, description: attachment["name"], diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex @@ -23,8 +23,8 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do with params <- Enum.into(:cow_qs.parse_qs(qs), %{}), sec_websocket <- :cowboy_req.header("sec-websocket-protocol", req, nil), access_token <- Map.get(params, "access_token"), - {:ok, user} <- authenticate_request(access_token, sec_websocket), - {:ok, topic} <- Streamer.get_topic(Map.get(params, "stream"), user, params) do + {:ok, user, oauth_token} <- authenticate_request(access_token, sec_websocket), + {:ok, topic} <- Streamer.get_topic(params["stream"], user, oauth_token, params) do req = if sec_websocket do :cowboy_req.set_resp_header("sec-websocket-protocol", sec_websocket, req) @@ -117,7 +117,7 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do # Public streams without authentication. defp authenticate_request(nil, nil) do - {:ok, nil} + {:ok, nil, nil} end # Authenticated streams. @@ -125,9 +125,9 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do token = access_token || sec_websocket with true <- is_bitstring(token), - %Token{user_id: user_id} <- Repo.get_by(Token, token: token), + oauth_token = %Token{user_id: user_id} <- Repo.get_by(Token, token: token), user = %User{} <- User.get_cached_by_id(user_id) do - {:ok, user} + {:ok, user, oauth_token} else _ -> {:error, :unauthorized} end diff --git a/lib/pleroma/web/media_proxy/invalidation.ex b/lib/pleroma/web/media_proxy/invalidation.ex @@ -33,6 +33,8 @@ defmodule Pleroma.Web.MediaProxy.Invalidation do def prepare_urls(urls) do urls |> List.wrap() - |> Enum.map(&MediaProxy.url/1) + |> Enum.map(fn url -> [MediaProxy.url(url), MediaProxy.preview_url(url)] end) + |> List.flatten() + |> Enum.uniq() end end diff --git a/lib/pleroma/web/media_proxy/media_proxy.ex b/lib/pleroma/web/media_proxy/media_proxy.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.MediaProxy do alias Pleroma.Config + alias Pleroma.Helpers.UriHelper alias Pleroma.Upload alias Pleroma.Web alias Pleroma.Web.MediaProxy.Invalidation @@ -40,27 +41,35 @@ defmodule Pleroma.Web.MediaProxy do def url("/" <> _ = url), do: url def url(url) do - if disabled?() or not url_proxiable?(url) do - url - else + if enabled?() and url_proxiable?(url) do encode_url(url) + else + url end end @spec url_proxiable?(String.t()) :: boolean() def url_proxiable?(url) do - if local?(url) or whitelisted?(url) do - false + not local?(url) and not whitelisted?(url) + end + + def preview_url(url, preview_params \\ []) do + if preview_enabled?() do + encode_preview_url(url, preview_params) else - true + url(url) end end - defp disabled?, do: !Config.get([:media_proxy, :enabled], false) + def enabled?, do: Config.get([:media_proxy, :enabled], false) + + # Note: media proxy must be enabled for media preview proxy in order to load all + # non-local non-whitelisted URLs through it and be sure that body size constraint is preserved. + def preview_enabled?, do: enabled?() and !!Config.get([:media_preview_proxy, :enabled]) - defp local?(url), do: String.starts_with?(url, Pleroma.Web.base_url()) + def local?(url), do: String.starts_with?(url, Pleroma.Web.base_url()) - defp whitelisted?(url) do + def whitelisted?(url) do %{host: domain} = URI.parse(url) mediaproxy_whitelist_domains = @@ -85,17 +94,29 @@ defmodule Pleroma.Web.MediaProxy do defp maybe_get_domain_from_url(domain), do: domain - def encode_url(url) do + defp base64_sig64(url) do base64 = Base.url_encode64(url, @base64_opts) sig64 = base64 - |> signed_url + |> signed_url() |> Base.url_encode64(@base64_opts) + {base64, sig64} + end + + def encode_url(url) do + {base64, sig64} = base64_sig64(url) + build_url(sig64, base64, filename(url)) end + def encode_preview_url(url, preview_params \\ []) do + {base64, sig64} = base64_sig64(url) + + build_preview_url(sig64, base64, filename(url), preview_params) + end + def decode_url(sig, url) do with {:ok, sig} <- Base.url_decode64(sig, @base64_opts), signature when signature == sig <- signed_url(url) do @@ -113,10 +134,14 @@ defmodule Pleroma.Web.MediaProxy do if path = URI.parse(url_or_path).path, do: Path.basename(path) end - def build_url(sig_base64, url_base64, filename \\ nil) do + def base_url do + Config.get([:media_proxy, :base_url], Web.base_url()) + end + + defp proxy_url(path, sig_base64, url_base64, filename) do [ - Config.get([:media_proxy, :base_url], Web.base_url()), - "proxy", + base_url(), + path, sig_base64, url_base64, filename @@ -124,4 +149,38 @@ defmodule Pleroma.Web.MediaProxy do |> Enum.filter(& &1) |> Path.join() end + + def build_url(sig_base64, url_base64, filename \\ nil) do + proxy_url("proxy", sig_base64, url_base64, filename) + end + + def build_preview_url(sig_base64, url_base64, filename \\ nil, preview_params \\ []) do + uri = proxy_url("proxy/preview", sig_base64, url_base64, filename) + + UriHelper.modify_uri_params(uri, preview_params) + end + + def verify_request_path_and_url( + %Plug.Conn{params: %{"filename" => _}, request_path: request_path}, + url + ) do + verify_request_path_and_url(request_path, url) + end + + def verify_request_path_and_url(request_path, url) when is_binary(request_path) do + filename = filename(url) + + if filename && not basename_matches?(request_path, filename) do + {:wrong_filename, filename} + else + :ok + end + end + + def verify_request_path_and_url(_, _), do: :ok + + defp basename_matches?(path, filename) do + basename = Path.basename(path) + basename == filename or URI.decode(basename) == filename or URI.encode(basename) == filename + end end diff --git a/lib/pleroma/web/media_proxy/media_proxy_controller.ex b/lib/pleroma/web/media_proxy/media_proxy_controller.ex @@ -5,44 +5,201 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do use Pleroma.Web, :controller + alias Pleroma.Config + alias Pleroma.Helpers.MediaHelper + alias Pleroma.Helpers.UriHelper alias Pleroma.ReverseProxy alias Pleroma.Web.MediaProxy + alias Plug.Conn - @default_proxy_opts [max_body_length: 25 * 1_048_576, http: [follow_redirect: true]] - - def remote(conn, %{"sig" => sig64, "url" => url64} = params) do - with config <- Pleroma.Config.get([:media_proxy], []), - true <- Keyword.get(config, :enabled, false), + def remote(conn, %{"sig" => sig64, "url" => url64}) do + with {_, true} <- {:enabled, MediaProxy.enabled?()}, {:ok, url} <- MediaProxy.decode_url(sig64, url64), {_, false} <- {:in_banned_urls, MediaProxy.in_banned_urls(url)}, - :ok <- filename_matches(params, conn.request_path, url) do - ReverseProxy.call(conn, url, Keyword.get(config, :proxy_opts, @default_proxy_opts)) + :ok <- MediaProxy.verify_request_path_and_url(conn, url) do + ReverseProxy.call(conn, url, media_proxy_opts()) else - error when error in [false, {:in_banned_urls, true}] -> - send_resp(conn, 404, Plug.Conn.Status.reason_phrase(404)) + {:enabled, false} -> + send_resp(conn, 404, Conn.Status.reason_phrase(404)) + + {:in_banned_urls, true} -> + send_resp(conn, 404, Conn.Status.reason_phrase(404)) {:error, :invalid_signature} -> - send_resp(conn, 403, Plug.Conn.Status.reason_phrase(403)) + send_resp(conn, 403, Conn.Status.reason_phrase(403)) {:wrong_filename, filename} -> redirect(conn, external: MediaProxy.build_url(sig64, url64, filename)) end end - def filename_matches(%{"filename" => _} = _, path, url) do - filename = MediaProxy.filename(url) + def preview(%Conn{} = conn, %{"sig" => sig64, "url" => url64}) do + with {_, true} <- {:enabled, MediaProxy.preview_enabled?()}, + {:ok, url} <- MediaProxy.decode_url(sig64, url64), + :ok <- MediaProxy.verify_request_path_and_url(conn, url) do + handle_preview(conn, url) + else + {:enabled, false} -> + send_resp(conn, 404, Conn.Status.reason_phrase(404)) + + {:error, :invalid_signature} -> + send_resp(conn, 403, Conn.Status.reason_phrase(403)) + + {:wrong_filename, filename} -> + redirect(conn, external: MediaProxy.build_preview_url(sig64, url64, filename)) + end + end + + defp handle_preview(conn, url) do + media_proxy_url = MediaProxy.url(url) + + with {:ok, %{status: status} = head_response} when status in 200..299 <- + Pleroma.HTTP.request("head", media_proxy_url, [], [], pool: :media) do + content_type = Tesla.get_header(head_response, "content-type") + content_length = Tesla.get_header(head_response, "content-length") + content_length = content_length && String.to_integer(content_length) + static = conn.params["static"] in ["true", true] + + cond do + static and content_type == "image/gif" -> + handle_jpeg_preview(conn, media_proxy_url) + + static -> + drop_static_param_and_redirect(conn) + + content_type == "image/gif" -> + redirect(conn, external: media_proxy_url) + + min_content_length_for_preview() > 0 and content_length > 0 and + content_length < min_content_length_for_preview() -> + redirect(conn, external: media_proxy_url) + + true -> + handle_preview(content_type, conn, media_proxy_url) + end + else + # If HEAD failed, redirecting to media proxy URI doesn't make much sense; returning an error + {_, %{status: status}} -> + send_resp(conn, :failed_dependency, "Can't fetch HTTP headers (HTTP #{status}).") + + {:error, :recv_response_timeout} -> + send_resp(conn, :failed_dependency, "HEAD request timeout.") + + _ -> + send_resp(conn, :failed_dependency, "Can't fetch HTTP headers.") + end + end + + defp handle_preview("image/png" <> _ = _content_type, conn, media_proxy_url) do + handle_png_preview(conn, media_proxy_url) + end + + defp handle_preview("image/" <> _ = _content_type, conn, media_proxy_url) do + handle_jpeg_preview(conn, media_proxy_url) + end + + defp handle_preview("video/" <> _ = _content_type, conn, media_proxy_url) do + handle_video_preview(conn, media_proxy_url) + end + + defp handle_preview(_unsupported_content_type, conn, media_proxy_url) do + fallback_on_preview_error(conn, media_proxy_url) + end + + defp handle_png_preview(conn, media_proxy_url) do + quality = Config.get!([:media_preview_proxy, :image_quality]) + {thumbnail_max_width, thumbnail_max_height} = thumbnail_max_dimensions() + + with {:ok, thumbnail_binary} <- + MediaHelper.image_resize( + media_proxy_url, + %{ + max_width: thumbnail_max_width, + max_height: thumbnail_max_height, + quality: quality, + format: "png" + } + ) do + conn + |> put_preview_response_headers(["image/png", "preview.png"]) + |> send_resp(200, thumbnail_binary) + else + _ -> + fallback_on_preview_error(conn, media_proxy_url) + end + end + + defp handle_jpeg_preview(conn, media_proxy_url) do + quality = Config.get!([:media_preview_proxy, :image_quality]) + {thumbnail_max_width, thumbnail_max_height} = thumbnail_max_dimensions() - if filename && does_not_match(path, filename) do - {:wrong_filename, filename} + with {:ok, thumbnail_binary} <- + MediaHelper.image_resize( + media_proxy_url, + %{max_width: thumbnail_max_width, max_height: thumbnail_max_height, quality: quality} + ) do + conn + |> put_preview_response_headers() + |> send_resp(200, thumbnail_binary) else - :ok + _ -> + fallback_on_preview_error(conn, media_proxy_url) end end - def filename_matches(_, _, _), do: :ok + defp handle_video_preview(conn, media_proxy_url) do + with {:ok, thumbnail_binary} <- + MediaHelper.video_framegrab(media_proxy_url) do + conn + |> put_preview_response_headers() + |> send_resp(200, thumbnail_binary) + else + _ -> + fallback_on_preview_error(conn, media_proxy_url) + end + end + + defp drop_static_param_and_redirect(conn) do + uri_without_static_param = + conn + |> current_url() + |> UriHelper.modify_uri_params(%{}, ["static"]) + + redirect(conn, external: uri_without_static_param) + end + + defp fallback_on_preview_error(conn, media_proxy_url) do + redirect(conn, external: media_proxy_url) + end + + defp put_preview_response_headers( + conn, + [content_type, filename] = _content_info \\ ["image/jpeg", "preview.jpg"] + ) do + conn + |> put_resp_header("content-type", content_type) + |> put_resp_header("content-disposition", "inline; filename=\"#{filename}\"") + |> put_resp_header("cache-control", ReverseProxy.default_cache_control_header()) + end + + defp thumbnail_max_dimensions do + config = media_preview_proxy_config() + + thumbnail_max_width = Keyword.fetch!(config, :thumbnail_max_width) + thumbnail_max_height = Keyword.fetch!(config, :thumbnail_max_height) + + {thumbnail_max_width, thumbnail_max_height} + end + + defp min_content_length_for_preview do + Keyword.get(media_preview_proxy_config(), :min_content_length, 0) + end + + defp media_preview_proxy_config do + Config.get!([:media_preview_proxy]) + end - defp does_not_match(path, filename) do - basename = Path.basename(path) - basename != filename and URI.decode(basename) != filename and URI.encode(basename) != filename + defp media_proxy_opts do + Config.get([:media_proxy, :proxy_opts], []) end end diff --git a/lib/pleroma/web/metadata/opengraph.ex b/lib/pleroma/web/metadata/opengraph.ex @@ -61,7 +61,7 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do @impl Provider def build_tags(%{user: user}) do - with truncated_bio = Utils.scrub_html_and_truncate(user.bio || "") do + with truncated_bio = Utils.scrub_html_and_truncate(user.bio) do [ {:meta, [ diff --git a/lib/pleroma/web/metadata/restrict_indexing.ex b/lib/pleroma/web/metadata/restrict_indexing.ex @@ -10,7 +10,9 @@ defmodule Pleroma.Web.Metadata.Providers.RestrictIndexing do """ @impl true - def build_tags(%{user: %{local: false}}) do + def build_tags(%{user: %{local: true, discoverable: true}}), do: [] + + def build_tags(_) do [ {:meta, [ @@ -19,7 +21,4 @@ defmodule Pleroma.Web.Metadata.Providers.RestrictIndexing do ], []} ] end - - @impl true - def build_tags(%{user: %{local: true}}), do: [] end diff --git a/lib/pleroma/web/metadata/twitter_card.ex b/lib/pleroma/web/metadata/twitter_card.ex @@ -40,7 +40,7 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do @impl Provider def build_tags(%{user: user}) do - with truncated_bio = Utils.scrub_html_and_truncate(user.bio || "") do + with truncated_bio = Utils.scrub_html_and_truncate(user.bio) do [ title_tag(user), {:meta, [property: "twitter:description", content: truncated_bio], []}, diff --git a/lib/pleroma/web/metadata/utils.ex b/lib/pleroma/web/metadata/utils.ex @@ -38,7 +38,7 @@ defmodule Pleroma.Web.Metadata.Utils do def scrub_html(content), do: content def attachment_url(url) do - MediaProxy.url(url) + MediaProxy.preview_url(url) end def user_name_string(user) do diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex @@ -119,7 +119,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do redirect_uri = redirect_uri(conn, redirect_uri) url_params = %{access_token: token.token} url_params = Maps.put_if_present(url_params, :state, params["state"]) - url = UriHelper.append_uri_params(redirect_uri, url_params) + url = UriHelper.modify_uri_params(redirect_uri, url_params) redirect(conn, external: url) else conn @@ -161,7 +161,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do redirect_uri = redirect_uri(conn, redirect_uri) url_params = %{code: auth.token} url_params = Maps.put_if_present(url_params, :state, auth_attrs["state"]) - url = UriHelper.append_uri_params(redirect_uri, url_params) + url = UriHelper.modify_uri_params(redirect_uri, url_params) redirect(conn, external: url) else conn @@ -200,7 +200,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do {:mfa_required, user, auth, _}, params ) do - {:ok, token} = MFA.Token.create_token(user, auth) + {:ok, token} = MFA.Token.create(user, auth) data = %{ "mfa_token" => token.token, @@ -582,7 +582,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do do: put_session(conn, :registration_id, registration_id) defp build_and_response_mfa_token(user, auth) do - with {:ok, token} <- MFA.Token.create_token(user, auth) do + with {:ok, token} <- MFA.Token.create(user, auth) do MFAView.render("mfa_response.json", %{token: token, user: user}) end end diff --git a/lib/pleroma/web/oauth/token.ex b/lib/pleroma/web/oauth/token.ex @@ -50,7 +50,7 @@ defmodule Pleroma.Web.OAuth.Token do true <- auth.app_id == app.id do user = if auth.user_id, do: User.get_cached_by_id(auth.user_id), else: %User{} - create_token( + create( app, user, %{scopes: auth.scopes} @@ -83,8 +83,22 @@ defmodule Pleroma.Web.OAuth.Token do |> validate_required([:valid_until]) end - @spec create_token(App.t(), User.t(), map()) :: {:ok, Token} | {:error, Changeset.t()} - def create_token(%App{} = app, %User{} = user, attrs \\ %{}) do + @spec create(App.t(), User.t(), map()) :: {:ok, Token} | {:error, Changeset.t()} + def create(%App{} = app, %User{} = user, attrs \\ %{}) do + with {:ok, token} <- do_create(app, user, attrs) do + if Pleroma.Config.get([:oauth2, :clean_expired_tokens]) do + Pleroma.Workers.PurgeExpiredToken.enqueue(%{ + token_id: token.id, + valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"), + mod: __MODULE__ + }) + end + + {:ok, token} + end + end + + defp do_create(app, user, attrs) do %__MODULE__{user_id: user.id, app_id: app.id} |> cast(%{scopes: attrs[:scopes] || app.scopes}, [:scopes]) |> validate_required([:scopes, :app_id]) @@ -105,11 +119,6 @@ defmodule Pleroma.Web.OAuth.Token do |> Repo.delete_all() end - def delete_expired_tokens do - Query.get_expired_tokens() - |> Repo.delete_all() - end - def get_user_tokens(%User{id: user_id}) do Query.get_by_user(user_id) |> Query.preload([:app]) diff --git a/lib/pleroma/web/oauth/token/clean_worker.ex b/lib/pleroma/web/oauth/token/clean_worker.ex @@ -1,38 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.OAuth.Token.CleanWorker do - @moduledoc """ - The module represents functions to clean an expired OAuth and MFA tokens. - """ - use GenServer - - @ten_seconds 10_000 - @one_day 86_400_000 - - alias Pleroma.MFA - alias Pleroma.Web.OAuth - alias Pleroma.Workers.BackgroundWorker - - def start_link(_), do: GenServer.start_link(__MODULE__, %{}) - - def init(_) do - Process.send_after(self(), :perform, @ten_seconds) - {:ok, nil} - end - - @doc false - def handle_info(:perform, state) do - BackgroundWorker.enqueue("clean_expired_tokens", %{}) - interval = Pleroma.Config.get([:oauth2, :clean_expired_tokens_interval], @one_day) - - Process.send_after(self(), :perform, interval) - {:noreply, state} - end - - def perform(:clean) do - OAuth.Token.delete_expired_tokens() - MFA.Token.delete_expired_tokens() - end -end diff --git a/lib/pleroma/web/oauth/token/query.ex b/lib/pleroma/web/oauth/token/query.ex @@ -33,12 +33,6 @@ defmodule Pleroma.Web.OAuth.Token.Query do from(q in query, where: q.id == ^id) end - @spec get_expired_tokens(query, DateTime.t() | nil) :: query - def get_expired_tokens(query \\ Token, date \\ nil) do - expired_date = date || Timex.now() - from(q in query, where: fragment("?", q.valid_until) < ^expired_date) - end - @spec get_by_user(query, String.t()) :: query def get_by_user(query \\ Token, user_id) do from(q in query, where: q.user_id == ^user_id) diff --git a/lib/pleroma/web/oauth/token/strategy/refresh_token.ex b/lib/pleroma/web/oauth/token/strategy/refresh_token.ex @@ -46,7 +46,7 @@ defmodule Pleroma.Web.OAuth.Token.Strategy.RefreshToken do defp create_access_token({:error, error}, _), do: {:error, error} defp create_access_token({:ok, token}, %{app: app, user: user} = token_params) do - Token.create_token(app, user, add_refresh_token(token_params, token.refresh_token)) + Token.create(app, user, add_refresh_token(token_params, token.refresh_token)) end defp add_refresh_token(params, token) do diff --git a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex @@ -156,13 +156,8 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do blocked_ap_ids = User.blocked_users_ap_ids(user) chats = - from(c in Chat, - where: c.user_id == ^user_id, - where: c.recipient not in ^blocked_ap_ids, - order_by: [desc: c.updated_at], - inner_join: u in User, - on: u.ap_id == c.recipient - ) + Chat.for_user_query(user_id) + |> where([c], c.recipient not in ^blocked_ap_ids) |> Repo.all() conn diff --git a/lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex b/lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex @@ -0,0 +1,61 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.UserImportController do + use Pleroma.Web, :controller + + require Logger + + alias Pleroma.Plugs.OAuthScopesPlug + alias Pleroma.User + alias Pleroma.Web.ApiSpec + + plug(OAuthScopesPlug, %{scopes: ["follow", "write:follows"]} when action == :follow) + plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks) + plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action == :mutes) + + plug(OpenApiSpex.Plug.CastAndValidate) + defdelegate open_api_operation(action), to: ApiSpec.UserImportOperation + + def follow(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do + follow(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) + end + + def follow(%{assigns: %{user: follower}, body_params: %{list: list}} = conn, _) do + identifiers = + list + |> String.split("\n") + |> Enum.map(&(&1 |> String.split(",") |> List.first())) + |> List.delete("Account address") + |> Enum.map(&(&1 |> String.trim() |> String.trim_leading("@"))) + |> Enum.reject(&(&1 == "")) + + User.Import.follow_import(follower, identifiers) + json(conn, "job started") + end + + def blocks(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do + blocks(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) + end + + def blocks(%{assigns: %{user: blocker}, body_params: %{list: list}} = conn, _) do + User.Import.blocks_import(blocker, prepare_user_identifiers(list)) + json(conn, "job started") + end + + def mutes(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do + mutes(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) + end + + def mutes(%{assigns: %{user: user}, body_params: %{list: list}} = conn, _) do + User.Import.mutes_import(user, prepare_user_identifiers(list)) + json(conn, "job started") + end + + defp prepare_user_identifiers(list) do + list + |> String.split() + |> Enum.map(&String.trim_leading(&1, "@")) + end +end diff --git a/lib/pleroma/web/pleroma_api/views/scrobble_view.ex b/lib/pleroma/web/pleroma_api/views/scrobble_view.ex @@ -10,14 +10,14 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleView do alias Pleroma.Activity alias Pleroma.HTML alias Pleroma.Object + alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.MastodonAPI.AccountView - alias Pleroma.Web.MastodonAPI.StatusView def render("show.json", %{activity: %Activity{data: %{"type" => "Listen"}} = activity} = opts) do object = Object.normalize(activity) - user = StatusView.get_user(activity.data["actor"]) + user = CommonAPI.get_user(activity.data["actor"]) created_at = Utils.to_masto_date(activity.data["published"]) %{ diff --git a/lib/pleroma/web/rel_me.ex b/lib/pleroma/web/rel_me.ex @@ -5,7 +5,8 @@ defmodule Pleroma.Web.RelMe do @options [ pool: :media, - max_body: 2_000_000 + max_body: 2_000_000, + recv_timeout: 2_000 ] if Pleroma.Config.get(:env) == :test do @@ -23,18 +24,8 @@ defmodule Pleroma.Web.RelMe do def parse(_), do: {:error, "No URL provided"} defp parse_url(url) do - opts = - if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Hackney do - Keyword.merge(@options, - recv_timeout: 2_000, - with_body: true - ) - else - @options - end - with {:ok, %Tesla.Env{body: html, status: status}} when status in 200..299 <- - Pleroma.HTTP.get(url, [], adapter: opts), + Pleroma.HTTP.get(url, [], @options), {:ok, html_tree} <- Floki.parse_document(html), data <- Floki.attribute(html_tree, "link[rel~=me]", "href") ++ diff --git a/lib/pleroma/web/rich_media/helpers.ex b/lib/pleroma/web/rich_media/helpers.ex @@ -9,14 +9,15 @@ defmodule Pleroma.Web.RichMedia.Helpers do alias Pleroma.Object alias Pleroma.Web.RichMedia.Parser - @rich_media_options [ + @options [ pool: :media, - max_body: 2_000_000 + max_body: 2_000_000, + recv_timeout: 2_000 ] @spec validate_page_url(URI.t() | binary()) :: :ok | :error defp validate_page_url(page_url) when is_binary(page_url) do - validate_tld = Pleroma.Config.get([Pleroma.Formatter, :validate_tld]) + validate_tld = Config.get([Pleroma.Formatter, :validate_tld]) page_url |> Linkify.Parser.url?(validate_tld: validate_tld) @@ -86,18 +87,8 @@ defmodule Pleroma.Web.RichMedia.Helpers do def rich_media_get(url) do headers = [{"user-agent", Pleroma.Application.user_agent() <> "; Bot"}] - options = - if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Hackney do - Keyword.merge(@rich_media_options, - recv_timeout: 2_000, - with_body: true - ) - else - @rich_media_options - end - head_check = - case Pleroma.HTTP.head(url, headers, adapter: options) do + case Pleroma.HTTP.head(url, headers, @options) do # If the HEAD request didn't reach the server for whatever reason, # we assume the GET that comes right after won't either {:error, _} = e -> @@ -112,7 +103,7 @@ defmodule Pleroma.Web.RichMedia.Helpers do :ok end - with :ok <- head_check, do: Pleroma.HTTP.get(url, headers, adapter: options) + with :ok <- head_check, do: Pleroma.HTTP.get(url, headers, @options) end defp check_content_type(headers) do @@ -128,7 +119,7 @@ defmodule Pleroma.Web.RichMedia.Helpers do end end - @max_body @rich_media_options[:max_body] + @max_body @options[:max_body] defp check_content_length(headers) do case List.keyfind(headers, "content-length", 0) do {_, maybe_content_length} -> diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex @@ -20,31 +20,61 @@ defmodule Pleroma.Web.RichMedia.Parser do with {:ok, data} <- get_cached_or_parse(url), {:ok, _} <- set_ttl_based_on_image(data, url) do {:ok, data} - else - error -> - Logger.error(fn -> "Rich media error: #{inspect(error)}" end) end end defp get_cached_or_parse(url) do - case Cachex.fetch!(:rich_media_cache, url, fn _ -> {:commit, parse_url(url)} end) do - {:ok, _data} = res -> - res - - {:error, :body_too_large} = e -> - e - - {:error, {:content_type, _}} = e -> - e - - # The TTL is not set for the errors above, since they are unlikely to change - # with time - {:error, _} = e -> - ttl = Pleroma.Config.get([:rich_media, :failure_backoff], 60_000) - Cachex.expire(:rich_media_cache, url, ttl) - e + case Cachex.fetch(:rich_media_cache, url, fn -> + case parse_url(url) do + {:ok, _} = res -> + {:commit, res} + + {:error, reason} = e -> + # Unfortunately we have to log errors here, instead of doing that + # along with ttl setting at the bottom. Otherwise we can get log spam + # if more than one process was waiting for the rich media card + # while it was generated. Ideally we would set ttl here as well, + # so we don't override it number_of_waiters_on_generation + # times, but one, obviously, can't set ttl for not-yet-created entry + # and Cachex doesn't support returning ttl from the fetch callback. + log_error(url, reason) + {:commit, e} + end + end) do + {action, res} when action in [:commit, :ok] -> + case res do + {:ok, _data} = res -> + res + + {:error, reason} = e -> + if action == :commit, do: set_error_ttl(url, reason) + e + end + + {:error, e} -> + {:error, {:cachex_error, e}} end end + + defp set_error_ttl(_url, :body_too_large), do: :ok + defp set_error_ttl(_url, {:content_type, _}), do: :ok + + # The TTL is not set for the errors above, since they are unlikely to change + # with time + + defp set_error_ttl(url, _reason) do + ttl = Pleroma.Config.get([:rich_media, :failure_backoff], 60_000) + Cachex.expire(:rich_media_cache, url, ttl) + :ok + end + + defp log_error(url, {:invalid_metadata, data}) do + Logger.debug(fn -> "Incomplete or invalid metadata for #{url}: #{inspect(data)}" end) + end + + defp log_error(url, reason) do + Logger.warn(fn -> "Rich media error for #{url}: #{inspect(reason)}" end) + end end @doc """ @@ -98,7 +128,7 @@ defmodule Pleroma.Web.RichMedia.Parser do end) end - defp parse_url(url) do + def parse_url(url) do with {:ok, %Tesla.Env{body: html}} <- Pleroma.Web.RichMedia.Helpers.rich_media_get(url), {:ok, html} <- Floki.parse_document(html) do html @@ -124,7 +154,7 @@ defmodule Pleroma.Web.RichMedia.Parser do end defp check_parsed_data(data) do - {:error, "Found metadata was invalid or incomplete: #{inspect(data)}"} + {:error, {:invalid_metadata, data}} end defp clean_parsed_data(data) do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex @@ -178,9 +178,14 @@ defmodule Pleroma.Web.Router do get("/users", AdminAPIController, :list_users) get("/users/:nickname", AdminAPIController, :user_show) get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) + get("/users/:nickname/chats", AdminAPIController, :list_user_chats) get("/instances/:instance/statuses", AdminAPIController, :list_instance_statuses) + get("/instance_document/:name", InstanceDocumentController, :show) + patch("/instance_document/:name", InstanceDocumentController, :update) + delete("/instance_document/:name", InstanceDocumentController, :delete) + patch("/users/confirm_email", AdminAPIController, :confirm_email) patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email) @@ -214,6 +219,10 @@ defmodule Pleroma.Web.Router do get("/media_proxy_caches", MediaProxyCacheController, :index) post("/media_proxy_caches/delete", MediaProxyCacheController, :delete) post("/media_proxy_caches/purge", MediaProxyCacheController, :purge) + + get("/chats/:id", ChatController, :show) + get("/chats/:id/messages", ChatController, :messages) + delete("/chats/:id/messages/:message_id", ChatController, :delete_message) end scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do @@ -260,14 +269,15 @@ defmodule Pleroma.Web.Router do post("/delete_account", UtilController, :delete_account) put("/notification_settings", UtilController, :update_notificaton_settings) post("/disable_account", UtilController, :disable_account) - - post("/blocks_import", UtilController, :blocks_import) - post("/follow_import", UtilController, :follow_import) end scope "/api/pleroma", Pleroma.Web.PleromaAPI do pipe_through(:authenticated_api) + post("/mutes_import", UserImportController, :mutes) + post("/blocks_import", UserImportController, :blocks) + post("/follow_import", UserImportController, :follow) + get("/accounts/mfa", TwoFactorAuthenticationController, :settings) get("/accounts/mfa/backup_codes", TwoFactorAuthenticationController, :backup_codes) get("/accounts/mfa/setup/:method", TwoFactorAuthenticationController, :setup) @@ -670,6 +680,8 @@ defmodule Pleroma.Web.Router do end scope "/proxy/", Pleroma.Web.MediaProxy do + get("/preview/:sig/:url", MediaProxyController, :preview) + get("/preview/:sig/:url/:filename", MediaProxyController, :preview) get("/:sig/:url", MediaProxyController, :remote) get("/:sig/:url/:filename", MediaProxyController, :remote) end diff --git a/lib/pleroma/web/streamer/streamer.ex b/lib/pleroma/web/streamer/streamer.ex @@ -11,10 +11,12 @@ defmodule Pleroma.Web.Streamer do alias Pleroma.Conversation.Participation alias Pleroma.Notification alias Pleroma.Object + alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.CommonAPI + alias Pleroma.Web.OAuth.Token alias Pleroma.Web.StreamerView @mix_env Mix.env() @@ -26,53 +28,87 @@ defmodule Pleroma.Web.Streamer do @user_streams ["user", "user:notification", "direct", "user:pleroma_chat"] @doc "Expands and authorizes a stream, and registers the process for streaming." - @spec get_topic_and_add_socket(stream :: String.t(), User.t() | nil, Map.t() | nil) :: + @spec get_topic_and_add_socket( + stream :: String.t(), + User.t() | nil, + Token.t() | nil, + Map.t() | nil + ) :: {:ok, topic :: String.t()} | {:error, :bad_topic} | {:error, :unauthorized} - def get_topic_and_add_socket(stream, user, params \\ %{}) do - case get_topic(stream, user, params) do + def get_topic_and_add_socket(stream, user, oauth_token, params \\ %{}) do + case get_topic(stream, user, oauth_token, params) do {:ok, topic} -> add_socket(topic, user) error -> error end end @doc "Expand and authorizes a stream" - @spec get_topic(stream :: String.t(), User.t() | nil, Map.t()) :: + @spec get_topic(stream :: String.t(), User.t() | nil, Token.t() | nil, Map.t()) :: {:ok, topic :: String.t()} | {:error, :bad_topic} - def get_topic(stream, user, params \\ %{}) + def get_topic(stream, user, oauth_token, params \\ %{}) # Allow all public steams. - def get_topic(stream, _, _) when stream in @public_streams do + def get_topic(stream, _user, _oauth_token, _params) when stream in @public_streams do {:ok, stream} end # Allow all hashtags streams. - def get_topic("hashtag", _, %{"tag" => tag}) do + def get_topic("hashtag", _user, _oauth_token, %{"tag" => tag} = _params) do {:ok, "hashtag:" <> tag} end # Expand user streams. - def get_topic(stream, %User{} = user, _) when stream in @user_streams do - {:ok, stream <> ":" <> to_string(user.id)} + def get_topic( + stream, + %User{id: user_id} = user, + %Token{user_id: token_user_id} = oauth_token, + _params + ) + when stream in @user_streams and user_id == token_user_id do + # Note: "read" works for all user streams (not mentioning it since it's an ancestor scope) + required_scopes = + if stream == "user:notification" do + ["read:notifications"] + else + ["read:statuses"] + end + + if OAuthScopesPlug.filter_descendants(required_scopes, oauth_token.scopes) == [] do + {:error, :unauthorized} + else + {:ok, stream <> ":" <> to_string(user.id)} + end end - def get_topic(stream, _, _) when stream in @user_streams do + def get_topic(stream, _user, _oauth_token, _params) when stream in @user_streams do {:error, :unauthorized} end # List streams. - def get_topic("list", %User{} = user, %{"list" => id}) do - if Pleroma.List.get(id, user) do - {:ok, "list:" <> to_string(id)} - else - {:error, :bad_topic} + def get_topic( + "list", + %User{id: user_id} = user, + %Token{user_id: token_user_id} = oauth_token, + %{"list" => id} + ) + when user_id == token_user_id do + cond do + OAuthScopesPlug.filter_descendants(["read", "read:lists"], oauth_token.scopes) == [] -> + {:error, :unauthorized} + + Pleroma.List.get(id, user) -> + {:ok, "list:" <> to_string(id)} + + true -> + {:error, :bad_topic} end end - def get_topic("list", _, _) do + def get_topic("list", _user, _oauth_token, _params) do {:error, :unauthorized} end - def get_topic(_, _, _) do + def get_topic(_stream, _user, _oauth_token, _params) do {:error, :bad_topic} end diff --git a/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex b/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex @@ -135,7 +135,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowController do end defp handle_follow_error(conn, {:mfa_required, followee, user, _} = _) do - {:ok, %{token: token}} = MFA.Token.create_token(user) + {:ok, %{token: token}} = MFA.Token.create(user) render(conn, "follow_mfa.html", %{followee: followee, mfa_token: token, error: false}) end diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -20,14 +20,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do plug( OAuthScopesPlug, - %{scopes: ["follow", "write:follows"]} - when action == :follow_import - ) - - plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks_import) - - plug( - OAuthScopesPlug, %{scopes: ["write:accounts"]} when action in [ :change_email, @@ -104,33 +96,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end end - def follow_import(conn, %{"list" => %Plug.Upload{} = listfile}) do - follow_import(conn, %{"list" => File.read!(listfile.path)}) - end - - def follow_import(%{assigns: %{user: follower}} = conn, %{"list" => list}) do - followed_identifiers = - list - |> String.split("\n") - |> Enum.map(&(&1 |> String.split(",") |> List.first())) - |> List.delete("Account address") - |> Enum.map(&(&1 |> String.trim() |> String.trim_leading("@"))) - |> Enum.reject(&(&1 == "")) - - User.follow_import(follower, followed_identifiers) - json(conn, "job started") - end - - def blocks_import(conn, %{"list" => %Plug.Upload{} = listfile}) do - blocks_import(conn, %{"list" => File.read!(listfile.path)}) - end - - def blocks_import(%{assigns: %{user: blocker}} = conn, %{"list" => list}) do - blocked_identifiers = list |> String.split() |> Enum.map(&String.trim_leading(&1, "@")) - User.blocks_import(blocker, blocked_identifiers) - json(conn, "job started") - end - def change_password(%{assigns: %{user: user}} = conn, params) do case CommonAPI.Utils.confirm_current_password(user, params["password"]) do {:ok, user} -> diff --git a/lib/pleroma/workers/background_worker.ex b/lib/pleroma/workers/background_worker.ex @@ -26,26 +26,10 @@ defmodule Pleroma.Workers.BackgroundWorker do User.perform(:force_password_reset, user) end - def perform(%Job{ - args: %{ - "op" => "blocks_import", - "blocker_id" => blocker_id, - "blocked_identifiers" => blocked_identifiers - } - }) do - blocker = User.get_cached_by_id(blocker_id) - {:ok, User.perform(:blocks_import, blocker, blocked_identifiers)} - end - - def perform(%Job{ - args: %{ - "op" => "follow_import", - "follower_id" => follower_id, - "followed_identifiers" => followed_identifiers - } - }) do - follower = User.get_cached_by_id(follower_id) - {:ok, User.perform(:follow_import, follower, followed_identifiers)} + def perform(%Job{args: %{"op" => op, "user_id" => user_id, "identifiers" => identifiers}}) + when op in ["blocks_import", "follow_import", "mutes_import"] do + user = User.get_cached_by_id(user_id) + {:ok, User.Import.perform(String.to_atom(op), user, identifiers)} end def perform(%Job{args: %{"op" => "media_proxy_preload", "message" => message}}) do diff --git a/lib/pleroma/workers/cron/clear_oauth_token_worker.ex b/lib/pleroma/workers/cron/clear_oauth_token_worker.ex @@ -1,23 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Workers.Cron.ClearOauthTokenWorker do - @moduledoc """ - The worker to cleanup expired oAuth tokens. - """ - - use Oban.Worker, queue: "background" - - alias Pleroma.Config - alias Pleroma.Web.OAuth.Token - - @impl Oban.Worker - def perform(_job) do - if Config.get([:oauth2, :clean_expired_tokens], false) do - Token.delete_expired_tokens() - end - - :ok - end -end diff --git a/lib/pleroma/workers/cron/purge_expired_activities_worker.ex b/lib/pleroma/workers/cron/purge_expired_activities_worker.ex @@ -1,48 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker do - @moduledoc """ - The worker to purge expired activities. - """ - - use Oban.Worker, queue: "activity_expiration" - - alias Pleroma.Activity - alias Pleroma.ActivityExpiration - alias Pleroma.Config - alias Pleroma.User - alias Pleroma.Web.CommonAPI - - require Logger - - @interval :timer.minutes(1) - - @impl Oban.Worker - def perform(_job) do - if Config.get([ActivityExpiration, :enabled]) do - Enum.each(ActivityExpiration.due_expirations(@interval), &delete_activity/1) - end - after - :ok - end - - def delete_activity(%ActivityExpiration{activity_id: activity_id}) do - with {:activity, %Activity{} = activity} <- - {:activity, Activity.get_by_id_with_object(activity_id)}, - {:user, %User{} = user} <- {:user, User.get_by_ap_id(activity.object.data["actor"])} do - CommonAPI.delete(activity.id, user) - else - {:activity, _} -> - Logger.error( - "#{__MODULE__} Couldn't delete expired activity: not found activity ##{activity_id}" - ) - - {:user, _} -> - Logger.error( - "#{__MODULE__} Couldn't delete expired activity: not found actor of ##{activity_id}" - ) - end - end -end diff --git a/lib/pleroma/workers/cron/stats_worker.ex b/lib/pleroma/workers/cron/stats_worker.ex @@ -1,17 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Workers.Cron.StatsWorker do - @moduledoc """ - The worker to update peers statistics. - """ - - use Oban.Worker, queue: "background" - - @impl Oban.Worker - def perform(_job) do - Pleroma.Stats.do_collect() - :ok - end -end diff --git a/lib/pleroma/workers/purge_expired_activity.ex b/lib/pleroma/workers/purge_expired_activity.ex @@ -0,0 +1,72 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.PurgeExpiredActivity do + @moduledoc """ + Worker which purges expired activity. + """ + + use Oban.Worker, queue: :activity_expiration, max_attempts: 1 + + import Ecto.Query + + alias Pleroma.Activity + + @spec enqueue(map()) :: + {:ok, Oban.Job.t()} + | {:error, :expired_activities_disabled} + | {:error, :expiration_too_close} + def enqueue(args) do + with true <- enabled?() do + {scheduled_at, args} = Map.pop(args, :expires_at) + + args + |> new(scheduled_at: scheduled_at) + |> Oban.insert() + end + end + + @impl true + def perform(%Oban.Job{args: %{"activity_id" => id}}) do + with %Activity{} = activity <- find_activity(id), + %Pleroma.User{} = user <- find_user(activity.object.data["actor"]) do + Pleroma.Web.CommonAPI.delete(activity.id, user) + end + end + + defp enabled? do + with false <- Pleroma.Config.get([__MODULE__, :enabled], false) do + {:error, :expired_activities_disabled} + end + end + + defp find_activity(id) do + with nil <- Activity.get_by_id_with_object(id) do + {:error, :activity_not_found} + end + end + + defp find_user(ap_id) do + with nil <- Pleroma.User.get_by_ap_id(ap_id) do + {:error, :user_not_found} + end + end + + def get_expiration(id) do + from(j in Oban.Job, + where: j.state == "scheduled", + where: j.queue == "activity_expiration", + where: fragment("?->>'activity_id' = ?", j.args, ^id) + ) + |> Pleroma.Repo.one() + end + + @spec expires_late_enough?(DateTime.t()) :: boolean() + def expires_late_enough?(scheduled_at) do + now = DateTime.utc_now() + diff = DateTime.diff(scheduled_at, now, :millisecond) + min_lifetime = Pleroma.Config.get([__MODULE__, :min_lifetime], 600) + diff > :timer.seconds(min_lifetime) + end +end diff --git a/lib/pleroma/workers/purge_expired_token.ex b/lib/pleroma/workers/purge_expired_token.ex @@ -0,0 +1,29 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.PurgeExpiredToken do + @moduledoc """ + Worker which purges expired OAuth tokens + """ + + use Oban.Worker, queue: :token_expiration, max_attempts: 1 + + @spec enqueue(%{token_id: integer(), valid_until: DateTime.t(), mod: module()}) :: + {:ok, Oban.Job.t()} | {:error, Ecto.Changeset.t()} + def enqueue(args) do + {scheduled_at, args} = Map.pop(args, :valid_until) + + args + |> __MODULE__.new(scheduled_at: scheduled_at) + |> Oban.insert() + end + + @impl true + def perform(%Oban.Job{args: %{"token_id" => id, "mod" => module}}) do + module + |> String.to_existing_atom() + |> Pleroma.Repo.get(id) + |> Pleroma.Repo.delete() + end +end diff --git a/mix.exs b/mix.exs @@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do def project do [ app: :pleroma, - version: version("2.1.2"), + version: version("2.1.50"), elixir: "~> 1.9", elixirc_paths: elixirc_paths(Mix.env()), compilers: [:phoenix, :gettext] ++ Mix.compilers(), @@ -134,7 +134,9 @@ defmodule Pleroma.Mixfile do {:cachex, "~> 3.2"}, {:poison, "~> 3.0", override: true}, {:tesla, - github: "teamon/tesla", ref: "af3707078b10793f6a534938e56b963aff82fe3c", override: true}, + git: "https://github.com/teamon/tesla/", + ref: "9f7261ca49f9f901ceb73b60219ad6f8a9f6aa30", + override: true}, {:castore, "~> 0.1"}, {:cowlib, "~> 2.9", override: true}, {:gun, @@ -178,7 +180,7 @@ defmodule Pleroma.Mixfile do {:flake_id, "~> 0.1.0"}, {:concurrent_limiter, git: "https://git.pleroma.social/pleroma/elixir-libraries/concurrent_limiter.git", - ref: "55e92f84b4ed531bd487952a71040a9c69dc2807"}, + ref: "d81be41024569330f296fc472e24198d7499ba78"}, {:remote_ip, git: "https://git.pleroma.social/pleroma/remote_ip.git", ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"}, diff --git a/mix.lock b/mix.lock @@ -14,7 +14,7 @@ "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "comeonin": {:hex, :comeonin, "5.3.1", "7fe612b739c78c9c1a75186ef2d322ce4d25032d119823269d0aa1e2f1e20025", [:mix], [], "hexpm", "d6222483060c17f0977fad1b7401ef0c5863c985a64352755f366aee3799c245"}, - "concurrent_limiter": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/concurrent_limiter.git", "55e92f84b4ed531bd487952a71040a9c69dc2807", [ref: "55e92f84b4ed531bd487952a71040a9c69dc2807"]}, + "concurrent_limiter": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/concurrent_limiter.git", "d81be41024569330f296fc472e24198d7499ba78", [ref: "d81be41024569330f296fc472e24198d7499ba78"]}, "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, "cors_plug": {:hex, :cors_plug, "2.0.2", "2b46083af45e4bc79632bd951550509395935d3e7973275b2b743bd63cc942ce", [:mix], [{:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f0d0e13f71c51fd4ef8b2c7e051388e4dfb267522a83a22392c856de7e46465f"}, "cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"}, @@ -31,6 +31,7 @@ "ecto": {:hex, :ecto, "3.4.5", "2bcd262f57b2c888b0bd7f7a28c8a48aa11dc1a2c6a858e45dd8f8426d504265", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8c6d1d4d524559e9b7a062f0498e2c206122552d63eacff0a6567ffe7a8e8691"}, "ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"}, "ecto_sql": {:hex, :ecto_sql, "3.4.5", "30161f81b167d561a9a2df4329c10ae05ff36eca7ccc84628f2c8b9fa1e43323", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31990c6a3579b36a3c0841d34a94c275e727de8b84f58509da5f1b2032c98ac2"}, + "eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"}, "elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm", "d522695b93b7f0b4c0fcb2dfe73a6b905b1c301226a5a55cb42e5b14d509e050"}, "esshd": {:hex, :esshd, "0.1.1", "d4dd4c46698093a40a56afecce8a46e246eb35463c457c246dacba2e056f31b5", [:mix], [], "hexpm", "d73e341e3009d390aa36387dc8862860bf9f874c94d9fd92ade2926376f49981"}, "eternal": {:hex, :eternal, "1.2.1", "d5b6b2499ba876c57be2581b5b999ee9bdf861c647401066d3eeed111d096bc4", [:mix], [], "hexpm", "b14f1dc204321429479c569cfbe8fb287541184ed040956c8862cb7a677b8406"}, @@ -80,6 +81,7 @@ "nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]}, "oban": {:hex, :oban, "2.0.0", "e6ce70d94dd46815ec0882a1ffb7356df9a9d5b8a40a64ce5c2536617a447379", [:mix], [{:ecto_sql, ">= 3.4.3", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cf574813bd048b98a698aa587c21367d2e06842d4e1b1993dcd6a696e9e633bd"}, "open_api_spex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git", "f296ac0924ba3cf79c7a588c4c252889df4c2edd", [ref: "f296ac0924ba3cf79c7a588c4c252889df4c2edd"]}, + "p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm", "1fc8773a71a15553b179c986b22fbeead19b28fe486c332d4929700ffeb71f88"}, "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"}, "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"}, "phoenix": {:hex, :phoenix, "1.4.17", "1b1bd4cff7cfc87c94deaa7d60dd8c22e04368ab95499483c50640ef3bd838d8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a8e5d7a3d76d452bb5fb86e8b7bd115f737e4f8efe202a463d4aeb4a5809611"}, @@ -110,7 +112,7 @@ "swoosh": {:hex, :swoosh, "1.0.0", "c547cfc83f30e12d5d1fdcb623d7de2c2e29a5becfc68bf8f42ba4d23d2c2756", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "b3b08e463f876cb6167f7168e9ad99a069a724e124bcee61847e0e1ed13f4a0d"}, "syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"}, "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"}, - "tesla": {:git, "https://github.com/teamon/tesla.git", "af3707078b10793f6a534938e56b963aff82fe3c", [ref: "af3707078b10793f6a534938e56b963aff82fe3c"]}, + "tesla": {:git, "https://github.com/teamon/tesla/", "9f7261ca49f9f901ceb73b60219ad6f8a9f6aa30", [ref: "9f7261ca49f9f901ceb73b60219ad6f8a9f6aa30"]}, "timex": {:hex, :timex, "3.6.2", "845cdeb6119e2fef10751c0b247b6c59d86d78554c83f78db612e3290f819bc2", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "26030b46199d02a590be61c2394b37ea25a3664c02fafbeca0b24c972025d47a"}, "trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"}, "tzdata": {:hex, :tzdata, "1.0.3", "73470ad29dde46e350c60a66e6b360d3b99d2d18b74c4c349dbebbc27a09a3eb", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a6e1ee7003c4d04ecbd21dd3ec690d4c6662db5d3bbdd7262d53cdf5e7c746c1"}, @@ -118,5 +120,5 @@ "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"}, "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"}, "web_push_encryption": {:hex, :web_push_encryption, "0.3.0", "598b5135e696fd1404dc8d0d7c0fa2c027244a4e5d5e5a98ba267f14fdeaabc8", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "f10bdd1afe527ede694749fb77a2f22f146a51b054c7fa541c9fd920fba7c875"}, - "websocket_client": {:git, "https://github.com/jeremyong/websocket_client.git", "9a6f65d05ebf2725d62fb19262b21f1805a59fbf", []}, + "websocket_client": {:git, "https://github.com/jeremyong/websocket_client.git", "9a6f65d05ebf2725d62fb19262b21f1805a59fbf", []} } diff --git a/priv/gettext/es/LC_MESSAGES/errors.po b/priv/gettext/es/LC_MESSAGES/errors.po @@ -0,0 +1,586 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-09-09 09:49+0000\n" +"PO-Revision-Date: 2020-09-11 21:26+0000\n" +"Last-Translator: tarteka <info@tarteka.net>\n" +"Language-Team: Spanish <https://translate.pleroma.social/projects/pleroma/" +"pleroma/es/>\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +## This file is a PO Template file. +## +## `msgid`s here are often extracted from source code. +## Add new translations manually only if they're dynamic +## translations that can't be statically extracted. +## +## Run `mix gettext.extract` to bring this file up to +## date. Leave `msgstr`s empty as changing them here as no +## effect: edit them in PO (`.po`) files instead. +## From Ecto.Changeset.cast/4 +msgid "can't be blank" +msgstr "no puede estar en blanco" + +## From Ecto.Changeset.unique_constraint/3 +msgid "has already been taken" +msgstr "ya está en uso" + +## From Ecto.Changeset.put_change/3 +msgid "is invalid" +msgstr "es inválido" + +## From Ecto.Changeset.validate_format/3 +msgid "has invalid format" +msgstr "el formato no es válido" + +## From Ecto.Changeset.validate_subset/3 +msgid "has an invalid entry" +msgstr "tiene una entrada inválida" + +## From Ecto.Changeset.validate_exclusion/3 +msgid "is reserved" +msgstr "está reservado" + +## From Ecto.Changeset.validate_confirmation/3 +msgid "does not match confirmation" +msgstr "la confirmación no coincide" + +## From Ecto.Changeset.no_assoc_constraint/3 +msgid "is still associated with this entry" +msgstr "todavía está asociado con esta entrada" + +msgid "are still associated with this entry" +msgstr "todavía están asociados con esta entrada" + +## From Ecto.Changeset.validate_length/3 +msgid "should be %{count} character(s)" +msgid_plural "should be %{count} character(s)" +msgstr[0] "debe tener %{count} carácter" +msgstr[1] "debe tener %{count} caracteres" + +msgid "should have %{count} item(s)" +msgid_plural "should have %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should be at least %{count} character(s)" +msgid_plural "should be at least %{count} character(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should have at least %{count} item(s)" +msgid_plural "should have at least %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should be at most %{count} character(s)" +msgid_plural "should be at most %{count} character(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should have at most %{count} item(s)" +msgid_plural "should have at most %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +## From Ecto.Changeset.validate_number/3 +msgid "must be less than %{number}" +msgstr "" + +msgid "must be greater than %{number}" +msgstr "debe ser mayor que %{number}" + +msgid "must be less than or equal to %{number}" +msgstr "debe ser menor o igual que %{number}" + +msgid "must be greater than or equal to %{number}" +msgstr "deber ser mayor o igual que %{number}" + +msgid "must be equal to %{number}" +msgstr "deber ser igual a %{number}" + +#: lib/pleroma/web/common_api/common_api.ex:505 +#, elixir-format +msgid "Account not found" +msgstr "Cuenta no encontrada" + +#: lib/pleroma/web/common_api/common_api.ex:339 +#, elixir-format +msgid "Already voted" +msgstr "Ya has votado" + +#: lib/pleroma/web/oauth/oauth_controller.ex:359 +#, elixir-format +msgid "Bad request" +msgstr "Solicitud incorrecta" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426 +#, elixir-format +msgid "Can't delete object" +msgstr "No se puede eliminar el objeto" + +#: lib/pleroma/web/controller_helper.ex:105 +#: lib/pleroma/web/controller_helper.ex:111 +#, elixir-format +msgid "Can't display this activity" +msgstr "No se puede mostrar esta actividad" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:285 +#, elixir-format +msgid "Can't find user" +msgstr "No se puede encontrar al usuario" + +#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61 +#, elixir-format +msgid "Can't get favorites" +msgstr "No se puede obtener los favoritos" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438 +#, elixir-format +msgid "Can't like object" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:563 +#, elixir-format +msgid "Cannot post an empty status without attachments" +msgstr "No se puede publicar un estado vacío y sin archivos adjuntos" + +#: lib/pleroma/web/common_api/utils.ex:511 +#, elixir-format +msgid "Comment must be up to %{max_size} characters" +msgstr "" + +#: lib/pleroma/config/config_db.ex:191 +#, elixir-format +msgid "Config with params %{params} not found" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:181 +#: lib/pleroma/web/common_api/common_api.ex:185 +#, elixir-format +msgid "Could not delete" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:231 +#, elixir-format +msgid "Could not favorite" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:453 +#, elixir-format +msgid "Could not pin" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:278 +#, elixir-format +msgid "Could not unfavorite" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:463 +#, elixir-format +msgid "Could not unpin" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:216 +#, elixir-format +msgid "Could not unrepeat" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:512 +#: lib/pleroma/web/common_api/common_api.ex:521 +#, elixir-format +msgid "Could not update state" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207 +#, elixir-format +msgid "Error." +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:106 +#, elixir-format +msgid "Invalid CAPTCHA" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116 +#: lib/pleroma/web/oauth/oauth_controller.ex:568 +#, elixir-format +msgid "Invalid credentials" +msgstr "" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 +#, elixir-format +msgid "Invalid credentials." +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:355 +#, elixir-format +msgid "Invalid indices" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid parameters" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:414 +#, elixir-format +msgid "Invalid password." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220 +#, elixir-format +msgid "Invalid request" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:109 +#, elixir-format +msgid "Kocaptcha service unavailable" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112 +#, elixir-format +msgid "Missing parameters" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:547 +#, elixir-format +msgid "No such conversation" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388 +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456 +#, elixir-format +msgid "No such permission_group" +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:84 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:486 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11 +#: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143 +#, elixir-format +msgid "Not found" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:331 +#, elixir-format +msgid "Poll's author can't vote" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:37 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:49 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:306 +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71 +#, elixir-format +msgid "Record not found" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35 +#: lib/pleroma/web/feed/user_controller.ex:77 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:36 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:149 +#, elixir-format +msgid "Something went wrong" +msgstr "" + +#: lib/pleroma/web/common_api/activity_draft.ex:107 +#, elixir-format +msgid "The message visibility must be direct" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:573 +#, elixir-format +msgid "The status is over the character limit" +msgstr "" + +#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 +#, elixir-format +msgid "This resource requires authentication." +msgstr "" + +#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 +#, elixir-format +msgid "Throttled" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:356 +#, elixir-format +msgid "Too many choices" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443 +#, elixir-format +msgid "Unhandled activity type" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485 +#, elixir-format +msgid "You can't revoke your own admin status." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:221 +#: lib/pleroma/web/oauth/oauth_controller.ex:308 +#, elixir-format +msgid "Your account is currently disabled" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:183 +#: lib/pleroma/web/oauth/oauth_controller.ex:331 +#, elixir-format +msgid "Your login is missing a confirmed e-mail address" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390 +#, elixir-format +msgid "can't read inbox of %{nickname} as %{as_nickname}" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473 +#, elixir-format +msgid "can't update outbox of %{nickname} as %{as_nickname}" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:471 +#, elixir-format +msgid "conversation is already muted" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:314 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:492 +#, elixir-format +msgid "error" +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32 +#, elixir-format +msgid "mascots can only be images" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62 +#, elixir-format +msgid "not found" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:394 +#, elixir-format +msgid "Bad OAuth request." +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:115 +#, elixir-format +msgid "CAPTCHA already used" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:112 +#, elixir-format +msgid "CAPTCHA expired" +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:57 +#, elixir-format +msgid "Failed" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:410 +#, elixir-format +msgid "Failed to authenticate: %{message}." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:441 +#, elixir-format +msgid "Failed to set up user account." +msgstr "" + +#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 +#, elixir-format +msgid "Insufficient permissions: %{permissions}." +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:104 +#, elixir-format +msgid "Internal Error" +msgstr "" + +#: lib/pleroma/web/oauth/fallback_controller.ex:22 +#: lib/pleroma/web/oauth/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid Username/Password" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:118 +#, elixir-format +msgid "Invalid answer data" +msgstr "" + +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33 +#, elixir-format +msgid "Nodeinfo schema version not handled" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:172 +#, elixir-format +msgid "This action is outside the authorized scopes" +msgstr "" + +#: lib/pleroma/web/oauth/fallback_controller.ex:14 +#, elixir-format +msgid "Unknown error, please check the details and try again." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:119 +#: lib/pleroma/web/oauth/oauth_controller.ex:158 +#, elixir-format +msgid "Unlisted redirect_uri." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:390 +#, elixir-format +msgid "Unsupported OAuth provider: %{provider}." +msgstr "" + +#: lib/pleroma/uploaders/uploader.ex:72 +#, elixir-format +msgid "Uploader callback timeout" +msgstr "" + +#: lib/pleroma/web/uploader_controller.ex:23 +#, elixir-format +msgid "bad request" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:103 +#, elixir-format +msgid "CAPTCHA Error" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:290 +#, elixir-format +msgid "Could not add reaction emoji" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:301 +#, elixir-format +msgid "Could not remove reaction emoji" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:129 +#, elixir-format +msgid "Invalid CAPTCHA (Missing parameter: %{name})" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 +#, elixir-format +msgid "List not found" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123 +#, elixir-format +msgid "Missing parameter: %{name}" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:210 +#: lib/pleroma/web/oauth/oauth_controller.ex:321 +#, elixir-format +msgid "Password reset is required" +msgstr "" + +#: lib/pleroma/tests/auth_test_controller.ex:9 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6 lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex:6 lib/pleroma/web/admin_api/controllers/relay_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6 lib/pleroma/web/admin_api/controllers/status_controller.ex:6 +#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/embed_controller.ex:6 +#: lib/pleroma/web/fallback_redirect_controller.ex:6 lib/pleroma/web/feed/tag_controller.ex:6 +#: lib/pleroma/web/feed/user_controller.ex:6 lib/pleroma/web/mailer/subscription_controller.ex:2 +#: lib/pleroma/web/masto_fe_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14 +#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8 +#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7 +#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6 +#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6 lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6 +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6 lib/pleroma/web/oauth/fallback_controller.ex:6 +#: lib/pleroma/web/oauth/mfa_controller.ex:10 lib/pleroma/web/oauth/oauth_controller.ex:6 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5 lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:2 lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6 +#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6 +#, elixir-format +msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped." +msgstr "" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 +#, elixir-format +msgid "Two-factor authentication enabled, you must use a access token." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210 +#, elixir-format +msgid "Unexpected error occurred while adding file to pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138 +#, elixir-format +msgid "Unexpected error occurred while creating pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278 +#, elixir-format +msgid "Unexpected error occurred while removing file from pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250 +#, elixir-format +msgid "Unexpected error occurred while updating file in pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179 +#, elixir-format +msgid "Unexpected error occurred while updating pack metadata." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 +#, elixir-format +msgid "Web push subscription is disabled on this Pleroma instance" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451 +#, elixir-format +msgid "You can't revoke your own admin/moderator status." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126 +#, elixir-format +msgid "authorization required for timeline view" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24 +#, elixir-format +msgid "Access denied" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282 +#, elixir-format +msgid "This API requires an authenticated user" +msgstr "" + +#: lib/pleroma/plugs/user_is_admin_plug.ex:21 +#, elixir-format +msgid "User is not an admin." +msgstr "" diff --git a/priv/gettext/zh_Hans/LC_MESSAGES/errors.po b/priv/gettext/zh_Hans/LC_MESSAGES/errors.po @@ -0,0 +1,580 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-09-20 13:18+0000\n" +"PO-Revision-Date: 2020-09-20 14:48+0000\n" +"Last-Translator: Kana <gudzpoz@live.com>\n" +"Language-Team: Chinese (Simplified) <https://translate.pleroma.social/" +"projects/pleroma/pleroma/zh_Hans/>\n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.0.4\n" + +## This file is a PO Template file. +## +## `msgid`s here are often extracted from source code. +## Add new translations manually only if they're dynamic +## translations that can't be statically extracted. +## +## Run `mix gettext.extract` to bring this file up to +## date. Leave `msgstr`s empty as changing them here as no +## effect: edit them in PO (`.po`) files instead. +## From Ecto.Changeset.cast/4 +msgid "can't be blank" +msgstr "不能为空" + +## From Ecto.Changeset.unique_constraint/3 +msgid "has already been taken" +msgstr "已被占用" + +## From Ecto.Changeset.put_change/3 +msgid "is invalid" +msgstr "不合法" + +## From Ecto.Changeset.validate_format/3 +msgid "has invalid format" +msgstr "的格式不合法" + +## From Ecto.Changeset.validate_subset/3 +msgid "has an invalid entry" +msgstr "中存在不合法的项目" + +## From Ecto.Changeset.validate_exclusion/3 +msgid "is reserved" +msgstr "是被保留的" + +## From Ecto.Changeset.validate_confirmation/3 +msgid "does not match confirmation" +msgstr "" + +## From Ecto.Changeset.no_assoc_constraint/3 +msgid "is still associated with this entry" +msgstr "仍与该项目相关联" + +msgid "are still associated with this entry" +msgstr "仍与该项目相关联" + +## From Ecto.Changeset.validate_length/3 +msgid "should be %{count} character(s)" +msgid_plural "should be %{count} character(s)" +msgstr[0] "应为 %{count} 个字符" + +msgid "should have %{count} item(s)" +msgid_plural "should have %{count} item(s)" +msgstr[0] "应有 %{item} 项" + +msgid "should be at least %{count} character(s)" +msgid_plural "should be at least %{count} character(s)" +msgstr[0] "应至少有 %{count} 个字符" + +msgid "should have at least %{count} item(s)" +msgid_plural "should have at least %{count} item(s)" +msgstr[0] "应至少有 %{count} 项" + +msgid "should be at most %{count} character(s)" +msgid_plural "should be at most %{count} character(s)" +msgstr[0] "应至多有 %{count} 个字符" + +msgid "should have at most %{count} item(s)" +msgid_plural "should have at most %{count} item(s)" +msgstr[0] "应至多有 %{count} 项" + +## From Ecto.Changeset.validate_number/3 +msgid "must be less than %{number}" +msgstr "必须小于 %{number}" + +msgid "must be greater than %{number}" +msgstr "必须大于 %{number}" + +msgid "must be less than or equal to %{number}" +msgstr "必须小于等于 %{number}" + +msgid "must be greater than or equal to %{number}" +msgstr "必须大于等于 %{number}" + +msgid "must be equal to %{number}" +msgstr "必须等于 %{number}" + +#: lib/pleroma/web/common_api/common_api.ex:505 +#, elixir-format +msgid "Account not found" +msgstr "未找到账号" + +#: lib/pleroma/web/common_api/common_api.ex:339 +#, elixir-format +msgid "Already voted" +msgstr "已经进行了投票" + +#: lib/pleroma/web/oauth/oauth_controller.ex:359 +#, elixir-format +msgid "Bad request" +msgstr "不正确的请求" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426 +#, elixir-format +msgid "Can't delete object" +msgstr "不能删除对象" + +#: lib/pleroma/web/controller_helper.ex:105 +#: lib/pleroma/web/controller_helper.ex:111 +#, elixir-format +msgid "Can't display this activity" +msgstr "不能显示该活动" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:285 +#, elixir-format +msgid "Can't find user" +msgstr "找不到用户" + +#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61 +#, elixir-format +msgid "Can't get favorites" +msgstr "不能获取收藏" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438 +#, elixir-format +msgid "Can't like object" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:563 +#, elixir-format +msgid "Cannot post an empty status without attachments" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:511 +#, elixir-format +msgid "Comment must be up to %{max_size} characters" +msgstr "" + +#: lib/pleroma/config/config_db.ex:191 +#, elixir-format +msgid "Config with params %{params} not found" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:181 +#: lib/pleroma/web/common_api/common_api.ex:185 +#, elixir-format +msgid "Could not delete" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:231 +#, elixir-format +msgid "Could not favorite" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:453 +#, elixir-format +msgid "Could not pin" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:278 +#, elixir-format +msgid "Could not unfavorite" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:463 +#, elixir-format +msgid "Could not unpin" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:216 +#, elixir-format +msgid "Could not unrepeat" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:512 +#: lib/pleroma/web/common_api/common_api.ex:521 +#, elixir-format +msgid "Could not update state" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207 +#, elixir-format +msgid "Error." +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:106 +#, elixir-format +msgid "Invalid CAPTCHA" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116 +#: lib/pleroma/web/oauth/oauth_controller.ex:568 +#, elixir-format +msgid "Invalid credentials" +msgstr "" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 +#, elixir-format +msgid "Invalid credentials." +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:355 +#, elixir-format +msgid "Invalid indices" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid parameters" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:414 +#, elixir-format +msgid "Invalid password." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220 +#, elixir-format +msgid "Invalid request" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:109 +#, elixir-format +msgid "Kocaptcha service unavailable" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112 +#, elixir-format +msgid "Missing parameters" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:547 +#, elixir-format +msgid "No such conversation" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388 +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456 +#, elixir-format +msgid "No such permission_group" +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:84 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:486 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11 +#: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143 +#, elixir-format +msgid "Not found" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:331 +#, elixir-format +msgid "Poll's author can't vote" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:37 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:49 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:306 +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71 +#, elixir-format +msgid "Record not found" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35 +#: lib/pleroma/web/feed/user_controller.ex:77 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:36 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:149 +#, elixir-format +msgid "Something went wrong" +msgstr "" + +#: lib/pleroma/web/common_api/activity_draft.ex:107 +#, elixir-format +msgid "The message visibility must be direct" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:573 +#, elixir-format +msgid "The status is over the character limit" +msgstr "" + +#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 +#, elixir-format +msgid "This resource requires authentication." +msgstr "" + +#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 +#, elixir-format +msgid "Throttled" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:356 +#, elixir-format +msgid "Too many choices" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443 +#, elixir-format +msgid "Unhandled activity type" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485 +#, elixir-format +msgid "You can't revoke your own admin status." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:221 +#: lib/pleroma/web/oauth/oauth_controller.ex:308 +#, elixir-format +msgid "Your account is currently disabled" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:183 +#: lib/pleroma/web/oauth/oauth_controller.ex:331 +#, elixir-format +msgid "Your login is missing a confirmed e-mail address" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390 +#, elixir-format +msgid "can't read inbox of %{nickname} as %{as_nickname}" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473 +#, elixir-format +msgid "can't update outbox of %{nickname} as %{as_nickname}" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:471 +#, elixir-format +msgid "conversation is already muted" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:314 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:492 +#, elixir-format +msgid "error" +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32 +#, elixir-format +msgid "mascots can only be images" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62 +#, elixir-format +msgid "not found" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:394 +#, elixir-format +msgid "Bad OAuth request." +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:115 +#, elixir-format +msgid "CAPTCHA already used" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:112 +#, elixir-format +msgid "CAPTCHA expired" +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:57 +#, elixir-format +msgid "Failed" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:410 +#, elixir-format +msgid "Failed to authenticate: %{message}." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:441 +#, elixir-format +msgid "Failed to set up user account." +msgstr "" + +#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 +#, elixir-format +msgid "Insufficient permissions: %{permissions}." +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:104 +#, elixir-format +msgid "Internal Error" +msgstr "" + +#: lib/pleroma/web/oauth/fallback_controller.ex:22 +#: lib/pleroma/web/oauth/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid Username/Password" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:118 +#, elixir-format +msgid "Invalid answer data" +msgstr "" + +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33 +#, elixir-format +msgid "Nodeinfo schema version not handled" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:172 +#, elixir-format +msgid "This action is outside the authorized scopes" +msgstr "" + +#: lib/pleroma/web/oauth/fallback_controller.ex:14 +#, elixir-format +msgid "Unknown error, please check the details and try again." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:119 +#: lib/pleroma/web/oauth/oauth_controller.ex:158 +#, elixir-format +msgid "Unlisted redirect_uri." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:390 +#, elixir-format +msgid "Unsupported OAuth provider: %{provider}." +msgstr "" + +#: lib/pleroma/uploaders/uploader.ex:72 +#, elixir-format +msgid "Uploader callback timeout" +msgstr "" + +#: lib/pleroma/web/uploader_controller.ex:23 +#, elixir-format +msgid "bad request" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:103 +#, elixir-format +msgid "CAPTCHA Error" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:290 +#, elixir-format +msgid "Could not add reaction emoji" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:301 +#, elixir-format +msgid "Could not remove reaction emoji" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:129 +#, elixir-format +msgid "Invalid CAPTCHA (Missing parameter: %{name})" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 +#, elixir-format +msgid "List not found" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123 +#, elixir-format +msgid "Missing parameter: %{name}" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:210 +#: lib/pleroma/web/oauth/oauth_controller.ex:321 +#, elixir-format +msgid "Password reset is required" +msgstr "" + +#: lib/pleroma/tests/auth_test_controller.ex:9 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6 lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex:6 lib/pleroma/web/admin_api/controllers/relay_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6 lib/pleroma/web/admin_api/controllers/status_controller.ex:6 +#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/embed_controller.ex:6 +#: lib/pleroma/web/fallback_redirect_controller.ex:6 lib/pleroma/web/feed/tag_controller.ex:6 +#: lib/pleroma/web/feed/user_controller.ex:6 lib/pleroma/web/mailer/subscription_controller.ex:2 +#: lib/pleroma/web/masto_fe_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14 +#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8 +#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7 +#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6 +#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6 lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6 +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6 lib/pleroma/web/oauth/fallback_controller.ex:6 +#: lib/pleroma/web/oauth/mfa_controller.ex:10 lib/pleroma/web/oauth/oauth_controller.ex:6 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5 lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:2 lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6 +#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6 +#, elixir-format +msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped." +msgstr "" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 +#, elixir-format +msgid "Two-factor authentication enabled, you must use a access token." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210 +#, elixir-format +msgid "Unexpected error occurred while adding file to pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138 +#, elixir-format +msgid "Unexpected error occurred while creating pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278 +#, elixir-format +msgid "Unexpected error occurred while removing file from pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250 +#, elixir-format +msgid "Unexpected error occurred while updating file in pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179 +#, elixir-format +msgid "Unexpected error occurred while updating pack metadata." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 +#, elixir-format +msgid "Web push subscription is disabled on this Pleroma instance" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451 +#, elixir-format +msgid "You can't revoke your own admin/moderator status." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126 +#, elixir-format +msgid "authorization required for timeline view" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24 +#, elixir-format +msgid "Access denied" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282 +#, elixir-format +msgid "This API requires an authenticated user" +msgstr "" + +#: lib/pleroma/plugs/user_is_admin_plug.ex:21 +#, elixir-format +msgid "User is not an admin." +msgstr "" diff --git a/priv/repo/migrations/20200824115541_rename_activity_expiration_setting.exs b/priv/repo/migrations/20200824115541_rename_activity_expiration_setting.exs @@ -0,0 +1,13 @@ +defmodule Pleroma.Repo.Migrations.RenameActivityExpirationSetting do + use Ecto.Migration + + def change do + config = Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.ActivityExpiration}) + + if config do + config + |> Ecto.Changeset.change(key: Pleroma.Workers.PurgeExpiredActivity) + |> Pleroma.Repo.update() + end + end +end diff --git a/priv/repo/migrations/20200825061316_move_activity_expirations_to_oban.exs b/priv/repo/migrations/20200825061316_move_activity_expirations_to_oban.exs @@ -0,0 +1,28 @@ +defmodule Pleroma.Repo.Migrations.MoveActivityExpirationsToOban do + use Ecto.Migration + + import Ecto.Query, only: [from: 2] + + def change do + Pleroma.Config.Oban.warn() + + Supervisor.start_link([{Oban, Pleroma.Config.get(Oban)}], + strategy: :one_for_one, + name: Pleroma.Supervisor + ) + + from(e in "activity_expirations", + select: %{id: e.id, activity_id: e.activity_id, scheduled_at: e.scheduled_at} + ) + |> Pleroma.Repo.stream() + |> Stream.each(fn expiration -> + with {:ok, expires_at} <- DateTime.from_naive(expiration.scheduled_at, "Etc/UTC") do + Pleroma.Workers.PurgeExpiredActivity.enqueue(%{ + activity_id: FlakeId.to_string(expiration.activity_id), + expires_at: expires_at + }) + end + end) + |> Stream.run() + end +end diff --git a/priv/repo/migrations/20200825093037_drop_activity_expirations_table.exs b/priv/repo/migrations/20200825093037_drop_activity_expirations_table.exs @@ -0,0 +1,7 @@ +defmodule Pleroma.Repo.Migrations.DropActivityExpirationsTable do + use Ecto.Migration + + def change do + drop(table("activity_expirations")) + end +end diff --git a/priv/repo/migrations/20200831142509_chat_constraints.exs b/priv/repo/migrations/20200831142509_chat_constraints.exs @@ -0,0 +1,22 @@ +defmodule Pleroma.Repo.Migrations.ChatConstraints do + use Ecto.Migration + + def change do + remove_orphans = """ + delete from chats where not exists(select id from users where ap_id = chats.recipient); + """ + + execute(remove_orphans) + + drop(constraint(:chats, "chats_user_id_fkey")) + + alter table(:chats) do + modify(:user_id, references(:users, type: :uuid, on_delete: :delete_all)) + + modify( + :recipient, + references(:users, column: :ap_id, type: :string, on_delete: :delete_all) + ) + end + end +end diff --git a/priv/repo/migrations/20200901061256_ensure_bio_is_string.exs b/priv/repo/migrations/20200901061256_ensure_bio_is_string.exs @@ -0,0 +1,7 @@ +defmodule Pleroma.Repo.Migrations.EnsureBioIsString do + use Ecto.Migration + + def change do + execute("update users set bio = '' where bio is null", "") + end +end diff --git a/priv/repo/migrations/20200901061637_bio_set_not_null.exs b/priv/repo/migrations/20200901061637_bio_set_not_null.exs @@ -0,0 +1,10 @@ +defmodule Pleroma.Repo.Migrations.BioSetNotNull do + use Ecto.Migration + + def change do + execute( + "alter table users alter column bio set not null", + "alter table users alter column bio drop not null" + ) + end +end diff --git a/priv/repo/migrations/20200905082737_rename_await_up_timeout_in_connections_pool.exs b/priv/repo/migrations/20200905082737_rename_await_up_timeout_in_connections_pool.exs @@ -0,0 +1,13 @@ +defmodule Pleroma.Repo.Migrations.RenameAwaitUpTimeoutInConnectionsPool do + use Ecto.Migration + + def change do + with %Pleroma.ConfigDB{} = config <- + Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: :connections_pool}), + {timeout, value} when is_integer(timeout) <- Keyword.pop(config.value, :await_up_timeout) do + config + |> Ecto.Changeset.change(value: Keyword.put(value, :connect_timeout, timeout)) + |> Pleroma.Repo.update() + end + end +end diff --git a/priv/repo/migrations/20200905091427_rename_timeout_in_pools.exs b/priv/repo/migrations/20200905091427_rename_timeout_in_pools.exs @@ -0,0 +1,19 @@ +defmodule Pleroma.Repo.Migrations.RenameTimeoutInPools do + use Ecto.Migration + + def change do + with %Pleroma.ConfigDB{} = config <- + Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: :pools}) do + updated_value = + Enum.map(config.value, fn {pool, pool_value} -> + with {timeout, value} when is_integer(timeout) <- Keyword.pop(pool_value, :timeout) do + {pool, Keyword.put(value, :recv_timeout, timeout)} + end + end) + + config + |> Ecto.Changeset.change(value: updated_value) + |> Pleroma.Repo.update() + end + end +end diff --git a/priv/repo/migrations/20200906072147_remove_cron_stats_worker_from_oban_config.exs b/priv/repo/migrations/20200906072147_remove_cron_stats_worker_from_oban_config.exs @@ -0,0 +1,19 @@ +defmodule Pleroma.Repo.Migrations.RemoveCronStatsWorkerFromObanConfig do + use Ecto.Migration + + def change do + with %Pleroma.ConfigDB{} = config <- + Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: Oban}), + crontab when is_list(crontab) <- config.value[:crontab], + index when is_integer(index) <- + Enum.find_index(crontab, fn {_, worker} -> + worker == Pleroma.Workers.Cron.StatsWorker + end) do + updated_value = Keyword.put(config.value, :crontab, List.delete_at(crontab, index)) + + config + |> Ecto.Changeset.change(value: updated_value) + |> Pleroma.Repo.update() + end + end +end diff --git a/priv/repo/migrations/20200907084956_remove_cron_clear_oauth_token_worker_from_oban_config.exs b/priv/repo/migrations/20200907084956_remove_cron_clear_oauth_token_worker_from_oban_config.exs @@ -0,0 +1,19 @@ +defmodule Pleroma.Repo.Migrations.RemoveCronClearOauthTokenWorkerFromObanConfig do + use Ecto.Migration + + def change do + with %Pleroma.ConfigDB{} = config <- + Pleroma.ConfigDB.get_by_params(%{group: :pleroma, key: Oban}), + crontab when is_list(crontab) <- config.value[:crontab], + index when is_integer(index) <- + Enum.find_index(crontab, fn {_, worker} -> + worker == Pleroma.Workers.Cron.ClearOauthTokenWorker + end) do + updated_value = Keyword.put(config.value, :crontab, List.delete_at(crontab, index)) + + config + |> Ecto.Changeset.change(value: updated_value) + |> Pleroma.Repo.update() + end + end +end diff --git a/priv/repo/migrations/20200907092050_move_tokens_expiration_into_oban.exs b/priv/repo/migrations/20200907092050_move_tokens_expiration_into_oban.exs @@ -0,0 +1,38 @@ +defmodule Pleroma.Repo.Migrations.MoveTokensExpirationIntoOban do + use Ecto.Migration + + import Ecto.Query, only: [from: 2] + + def change do + Pleroma.Config.Oban.warn() + + Supervisor.start_link([{Oban, Pleroma.Config.get(Oban)}], + strategy: :one_for_one, + name: Pleroma.Supervisor + ) + + if Pleroma.Config.get([:oauth2, :clean_expired_tokens]) do + from(t in Pleroma.Web.OAuth.Token, where: t.valid_until > ^NaiveDateTime.utc_now()) + |> Pleroma.Repo.stream() + |> Stream.each(fn token -> + Pleroma.Workers.PurgeExpiredToken.enqueue(%{ + token_id: token.id, + valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"), + mod: Pleroma.Web.OAuth.Token + }) + end) + |> Stream.run() + end + + from(t in Pleroma.MFA.Token, where: t.valid_until > ^NaiveDateTime.utc_now()) + |> Pleroma.Repo.stream() + |> Stream.each(fn token -> + Pleroma.Workers.PurgeExpiredToken.enqueue(%{ + token_id: token.id, + valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"), + mod: Pleroma.MFA.Token + }) + end) + |> Stream.run() + end +end diff --git a/priv/repo/migrations/20200910113106_remove_managed_config_from_db.exs b/priv/repo/migrations/20200910113106_remove_managed_config_from_db.exs @@ -0,0 +1,27 @@ +defmodule Pleroma.Repo.Migrations.RemoveManagedConfigFromDb do + use Ecto.Migration + import Ecto.Query + alias Pleroma.ConfigDB + alias Pleroma.Repo + + def up do + config_entry = + from(c in ConfigDB, + select: [:id, :value], + where: c.group == ^:pleroma and c.key == ^:instance + ) + |> Repo.one() + + if config_entry do + {_, value} = Keyword.pop(config_entry.value, :managed_config) + + config_entry + |> Ecto.Changeset.change(value: value) + |> Repo.update() + end + end + + def down do + :ok + end +end diff --git a/priv/repo/migrations/20200911055909_remove_cron_jobs.exs b/priv/repo/migrations/20200911055909_remove_cron_jobs.exs @@ -0,0 +1,20 @@ +defmodule Pleroma.Repo.Migrations.RemoveCronJobs do + use Ecto.Migration + + import Ecto.Query, only: [from: 2] + + def up do + from(j in "oban_jobs", + where: + j.worker in ^[ + "Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker", + "Pleroma.Workers.Cron.StatsWorker", + "Pleroma.Workers.Cron.ClearOauthTokenWorker" + ], + select: [:id] + ) + |> Pleroma.Repo.delete_all() + end + + def down, do: :ok +end diff --git a/priv/repo/migrations/20200914105638_delete_notification_without_activity.exs b/priv/repo/migrations/20200914105638_delete_notification_without_activity.exs @@ -0,0 +1,30 @@ +defmodule Pleroma.Repo.Migrations.DeleteNotificationWithoutActivity do + use Ecto.Migration + + import Ecto.Query + alias Pleroma.Repo + + def up do + from( + q in Pleroma.Notification, + left_join: c in assoc(q, :activity), + select: %{id: type(q.id, :integer)}, + where: is_nil(c.id) + ) + |> Repo.chunk_stream(1_000, :batches) + |> Stream.each(fn records -> + notification_ids = Enum.map(records, fn %{id: id} -> id end) + + Repo.delete_all( + from(n in "notifications", + where: n.id in ^notification_ids + ) + ) + end) + |> Stream.run() + end + + def down do + :ok + end +end diff --git a/priv/repo/migrations/20200914105800_add_notification_constraints.exs b/priv/repo/migrations/20200914105800_add_notification_constraints.exs @@ -0,0 +1,23 @@ +defmodule Pleroma.Repo.Migrations.AddNotificationConstraints do + use Ecto.Migration + + def up do + drop(constraint(:notifications, "notifications_activity_id_fkey")) + + alter table(:notifications) do + modify(:activity_id, references(:activities, type: :uuid, on_delete: :delete_all), + null: false + ) + end + end + + def down do + drop(constraint(:notifications, "notifications_activity_id_fkey")) + + alter table(:notifications) do + modify(:activity_id, references(:activities, type: :uuid, on_delete: :delete_all), + null: true + ) + end + end +end diff --git a/test/activity_expiration_test.exs b/test/activity_expiration_test.exs @@ -1,55 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.ActivityExpirationTest do - use Pleroma.DataCase - alias Pleroma.ActivityExpiration - import Pleroma.Factory - - setup do: clear_config([ActivityExpiration, :enabled]) - - test "finds activities due to be deleted only" do - activity = insert(:note_activity) - - expiration_due = - insert(:expiration_in_the_past, %{activity_id: activity.id}) |> Repo.preload(:activity) - - activity2 = insert(:note_activity) - insert(:expiration_in_the_future, %{activity_id: activity2.id}) - - expirations = ActivityExpiration.due_expirations() - - assert length(expirations) == 1 - assert hd(expirations) == expiration_due - end - - test "denies expirations that don't live long enough" do - activity = insert(:note_activity) - now = NaiveDateTime.utc_now() - assert {:error, _} = ActivityExpiration.create(activity, now) - end - - test "deletes an expiration activity" do - Pleroma.Config.put([ActivityExpiration, :enabled], true) - activity = insert(:note_activity) - - naive_datetime = - NaiveDateTime.add( - NaiveDateTime.utc_now(), - -:timer.minutes(2), - :millisecond - ) - - expiration = - insert( - :expiration_in_the_past, - %{activity_id: activity.id, scheduled_at: naive_datetime} - ) - - Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{}) - - refute Pleroma.Repo.get(Pleroma.Activity, activity.id) - refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id) - end -end diff --git a/test/activity_test.exs b/test/activity_test.exs @@ -185,15 +185,6 @@ defmodule Pleroma.ActivityTest do end end - test "add an activity with an expiration" do - activity = insert(:note_activity) - insert(:expiration_in_the_future, %{activity_id: activity.id}) - - Pleroma.ActivityExpiration - |> where([a], a.activity_id == ^activity.id) - |> Repo.one!() - end - test "all_by_ids_with_object/1" do %{id: id1} = insert(:note_activity) %{id: id2} = insert(:note_activity) diff --git a/test/chat_test.exs b/test/chat_test.exs @@ -26,6 +26,28 @@ defmodule Pleroma.ChatTest do assert chat.id end + test "deleting the user deletes the chat" do + user = insert(:user) + other_user = insert(:user) + + {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) + + Repo.delete(user) + + refute Chat.get_by_id(chat.id) + end + + test "deleting the recipient deletes the chat" do + user = insert(:user) + other_user = insert(:user) + + {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) + + Repo.delete(other_user) + + refute Chat.get_by_id(chat.id) + end + test "it returns and bumps a chat for a user and recipient if it already exists" do user = insert(:user) other_user = insert(:user) diff --git a/test/config/deprecation_warnings_test.exs b/test/config/deprecation_warnings_test.exs @@ -4,12 +4,15 @@ defmodule Pleroma.Config.DeprecationWarningsTest do import ExUnit.CaptureLog + alias Pleroma.Config + alias Pleroma.Config.DeprecationWarnings + test "check_old_mrf_config/0" do clear_config([:instance, :rewrite_policy], Pleroma.Web.ActivityPub.MRF.NoOpPolicy) clear_config([:instance, :mrf_transparency], true) clear_config([:instance, :mrf_transparency_exclusions], []) - assert capture_log(fn -> Pleroma.Config.DeprecationWarnings.check_old_mrf_config() end) =~ + assert capture_log(fn -> DeprecationWarnings.check_old_mrf_config() end) =~ """ !!!DEPRECATION WARNING!!! Your config is using old namespaces for MRF configuration. They should work for now, but you are advised to change to new namespaces to prevent possible issues later: @@ -44,22 +47,66 @@ defmodule Pleroma.Config.DeprecationWarningsTest do ] assert capture_log(fn -> - Pleroma.Config.DeprecationWarnings.move_namespace_and_warn( + DeprecationWarnings.move_namespace_and_warn( config_map, "Warning preface" ) end) =~ "Warning preface\n error :key\n error :key2\n error :key3" - assert Pleroma.Config.get(new_group1) == 1 - assert Pleroma.Config.get(new_group2) == 2 - assert Pleroma.Config.get(new_group3) == 3 + assert Config.get(new_group1) == 1 + assert Config.get(new_group2) == 2 + assert Config.get(new_group3) == 3 end test "check_media_proxy_whitelist_config/0" do clear_config([:media_proxy, :whitelist], ["https://example.com", "example2.com"]) assert capture_log(fn -> - Pleroma.Config.DeprecationWarnings.check_media_proxy_whitelist_config() + DeprecationWarnings.check_media_proxy_whitelist_config() end) =~ "Your config is using old format (only domain) for MediaProxy whitelist option" end + + describe "check_gun_pool_options/0" do + test "await_up_timeout" do + config = Config.get(:connections_pool) + clear_config(:connections_pool, Keyword.put(config, :await_up_timeout, 5_000)) + + assert capture_log(fn -> + DeprecationWarnings.check_gun_pool_options() + end) =~ + "Your config is using old setting name `await_up_timeout` instead of `connect_timeout`" + end + + test "pool timeout" do + old_config = [ + federation: [ + size: 50, + max_waiting: 10, + timeout: 10_000 + ], + media: [ + size: 50, + max_waiting: 10, + timeout: 10_000 + ], + upload: [ + size: 25, + max_waiting: 5, + timeout: 15_000 + ], + default: [ + size: 10, + max_waiting: 2, + timeout: 5_000 + ] + ] + + clear_config(:pools, old_config) + + assert capture_log(fn -> + DeprecationWarnings.check_gun_pool_options() + end) =~ + "Your config is using old setting name `timeout` instead of `recv_timeout` in pool settings" + end + end end diff --git a/test/fixtures/23211.atom b/test/fixtures/23211.atom @@ -1,508 +0,0 @@ -<?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-02T14:59:30+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/api/statuses/user_timeline/23211.atom?max_id=2012090" rel="next" type="application/atom+xml"/> - <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-02:fave:23211:comment:2015260:2017-05-02T14:45:47+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by godemperorofdune: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; It's because your instance decided to be trap! lol.&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2015305"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T14:45:47+00:00</published> - <updated>2017-05-02T14:45:47+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:pawoo.net,2017-05-02:objectId=7397439:objectType=Status</id> - <title>New comment by godemperorofdune</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; It's because your instance decided to be trap! lol.&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/God_Emperor_of_Dune/updates/2090090"/> - <status_net notice_id="2015260"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:pawoo.net,2017-05-02:objectId=7397439:objectType=Status" href="https://pawoo.net/users/God_Emperor_of_Dune/updates/2090090"></thr:in-reply-to> - <link rel="related" href="https://pawoo.net/users/God_Emperor_of_Dune/updates/2090090"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1035308"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1035308" local_id="1035308" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=136e244b26cdf1e9">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=136e244b26cdf1e9</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/2015305.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2015305.atom"/> - <statusnet:notice_info local_id="2015305" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-05-02:noticeId=2015221:objectType=note</id> - <title>New note by lambadalambda</title> - <content type="html">Some script thinks I'm a mastodon server.&lt;br /&gt; &lt;br /&gt; [info] GET /api/v1/timelines/public&lt;br /&gt; [debug] Processing with Fallback.RedirectController.redirector/2&lt;br /&gt; Parameters: %{&amp;quot;limit&amp;quot; =&amp;gt; &amp;quot;40&amp;quot;, &amp;quot;path&amp;quot; =&amp;gt; [&amp;quot;api&amp;quot;, &amp;quot;v1&amp;quot;, &amp;quot;timelines&amp;quot;, &amp;quot;public&amp;quot;]}&lt;br /&gt; Pipelines: []</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2015221"/> - <status_net notice_id="2015221"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-02T14:40:50+00:00</published> - <updated>2017-05-02T14:40:50+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1035308"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1035308" local_id="1035308" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=136e244b26cdf1e9">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=136e244b26cdf1e9</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/2015221.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2015221.atom"/> - <statusnet:notice_info local_id="2015221" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-05-02:noticeId=2014759:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://mstdn.io/users/mattskala&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Matthew Skala&quot;&gt;mattskala&lt;/a&gt; You and @&lt;a href=&quot;https://mastodon.social/users/kevinmarks&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Kevin Marks&quot;&gt;kevinmarks&lt;/a&gt; are not wrong, but my comment was a suggestion to users and admins: Don't use big instances, don't run big instances. Also, it's a secondary advice to devs: Don't add features that encourage big instances.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2014759"/> - <status_net notice_id="2014759"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-02T14:11:54+00:00</published> - <updated>2017-05-02T14:11:54+00:00</updated> - <thr:in-reply-to ref="tag:mstdn.io,2017-05-02:objectId=1316931:objectType=Status" href="https://mstdn.io/users/mattskala/updates/35698"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/users/mattskala/updates/35698"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1031866"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1031866" local_id="1031866" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/kevinmarks"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mstdn.io/users/mattskala"/> - <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/2014759.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2014759.atom"/> - <statusnet:notice_info local_id="2014759" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-05-02:noticeId=2014684:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://mastodon.social/users/Ronkjeffries&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Ron K Jeffries social&quot;&gt;ronkjeffries&lt;/a&gt; @&lt;a href=&quot;https://xoxo.zone/users/KevinMarks&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Kevin Marks &quot;&gt;kevinmarks&lt;/a&gt; Usually people who run their own private instance just look at the timelines of other servers, follow a seed population and then go from there. This is of course hard on Mastodon, because it doesn't have a publicly visible timeline.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2014684"/> - <status_net notice_id="2014684"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-02T14:07:00+00:00</published> - <updated>2017-05-02T14:07:00+00:00</updated> - <thr:in-reply-to ref="tag:mastodon.social,2017-05-02:objectId=4883853:objectType=Status" href="https://mastodon.social/users/Ronkjeffries/updates/2221244"></thr:in-reply-to> - <link rel="related" href="https://mastodon.social/users/Ronkjeffries/updates/2221244"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1031866"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1031866" local_id="1031866" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://xoxo.zone/users/KevinMarks"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/Ronkjeffries"/> - <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/2014684.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2014684.atom"/> - <statusnet:notice_info local_id="2014684" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2014584:2017-05-02T14:05:32+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by mattskala: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; It's reasonable to expect that instance sizes will obey a power-law distribution because that's what such things in nature nearly always do. If so, there'll necessarily be a few instances much larger than the others; even if most are small, the network both socially and technically has to be able to deal with the existence of the few large ones.&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2014659"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T14:05:32+00:00</published> - <updated>2017-05-02T14:05:32+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:mstdn.io,2017-05-02:objectId=1316931:objectType=Status</id> - <title>New comment by mattskala</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; It's reasonable to expect that instance sizes will obey a power-law distribution because that's what such things in nature nearly always do. If so, there'll necessarily be a few instances much larger than the others; even if most are small, the network both socially and technically has to be able to deal with the existence of the few large ones.&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mstdn.io/users/mattskala/updates/35698"/> - <status_net notice_id="2014584"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:mstdn.io,2017-05-02:objectId=1316931:objectType=Status" href="https://mstdn.io/users/mattskala/updates/35698"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/users/mattskala/updates/35698"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1031866"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1031866" local_id="1031866" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d</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/2014659.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2014659.atom"/> - <statusnet:notice_info local_id="2014659" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2013568:2017-05-02T14:05:29+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by kevinmarks: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; except instance populations will be power law distributed, and the problems for the tummlers are worse at scale&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2014657"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T14:05:29+00:00</published> - <updated>2017-05-02T14:05:29+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:xoxo.zone,2017-05-02:objectId=89478:objectType=Status</id> - <title>New comment by kevinmarks</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; except instance populations will be power law distributed, and the problems for the tummlers are worse at scale&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://xoxo.zone/users/KevinMarks/updates/1749"/> - <status_net notice_id="2013568"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:xoxo.zone,2017-05-02:objectId=89478:objectType=Status" href="https://xoxo.zone/users/KevinMarks/updates/1749"></thr:in-reply-to> - <link rel="related" href="https://xoxo.zone/users/KevinMarks/updates/1749"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1031866"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1031866" local_id="1031866" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d</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/2014657.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2014657.atom"/> - <statusnet:notice_info local_id="2014657" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2014060:2017-05-02T13:34:32+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by gcarregues: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Oh purée ! Ma vie en images !&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2014147"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T13:34:32+00:00</published> - <updated>2017-05-02T13:34:32+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:mastodon.etalab.gouv.fr,2017-05-02:objectId=55287:objectType=Status</id> - <title>New comment by gcarregues</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Oh purée ! Ma vie en images !&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mastodon.etalab.gouv.fr/users/gcarregues/updates/4370"/> - <status_net notice_id="2014060"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:mastodon.etalab.gouv.fr,2017-05-02:objectId=55287:objectType=Status" href="https://mastodon.etalab.gouv.fr/users/gcarregues/updates/4370"></thr:in-reply-to> - <link rel="related" href="https://mastodon.etalab.gouv.fr/users/gcarregues/updates/4370"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034065"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034065" local_id="1034065" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc</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/2014147.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2014147.atom"/> - <statusnet:notice_info local_id="2014147" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:note:2013573:2017-05-02T13:03:33+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by phildobangnz: also @&lt;a href=&quot;https://sealion.club/user/579&quot; class=&quot;h-card mention&quot; title=&quot;Sim Bot&quot;&gt;sim&lt;/a&gt; reminder you are awesome; don't even trip- u kewler than Tutankhamen's cucumber, fam. Okay, good night.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013702"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T13:03:33+00:00</published> - <updated>2017-05-02T13:03:33+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:sealion.club,2017-05-02:noticeId=3060818:objectType=note</id> - <title>New note by phildobangnz</title> - <content type="html">also @&lt;a href=&quot;https://sealion.club/user/579&quot; class=&quot;h-card mention&quot; title=&quot;Sim Bot&quot;&gt;sim&lt;/a&gt; reminder you are awesome; don't even trip- u kewler than Tutankhamen's cucumber, fam. Okay, good night.</content> - <link rel="alternate" type="text/html" href="https://sealion.club/notice/3060818"/> - <status_net notice_id="2013573"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:sealion.club,2017-05-02:noticeId=3060818:objectType=note" href="https://sealion.club/notice/3060818"></thr:in-reply-to> - <link rel="related" href="https://sealion.club/notice/3060818"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034282"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034282" local_id="1034282" ref="https://sealion.club/conversation/1633267">https://sealion.club/conversation/1633267</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/2013702.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013702.atom"/> - <statusnet:notice_info local_id="2013702" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-05-02:noticeId=2013586:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://xoxo.zone/users/KevinMarks&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Kevin Marks &quot;&gt;kevinmarks&lt;/a&gt; People can stay in their giant unmoderatable instances with meaningless public and federated timelines and experience constant federation drama if they want. I'll stay here with my 5 friends.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013586"/> - <status_net notice_id="2013586"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-02T12:54:59+00:00</published> - <updated>2017-05-02T12:54:59+00:00</updated> - <thr:in-reply-to ref="tag:xoxo.zone,2017-05-02:objectId=89478:objectType=Status" href="https://xoxo.zone/users/KevinMarks/updates/1749"></thr:in-reply-to> - <link rel="related" href="https://xoxo.zone/users/KevinMarks/updates/1749"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1031866"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1031866" local_id="1031866" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=58e32e013ab6487d</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://xoxo.zone/users/KevinMarks"/> - <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/2013586.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013586.atom"/> - <statusnet:notice_info local_id="2013586" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:note:2013486:2017-05-02T12:46:48+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by fortune: There once was a dentist named Stone&lt;br /&gt; Who saw all his patients alone.&lt;br /&gt; In a fit of depravity&lt;br /&gt; He filled the wrong cavity,&lt;br /&gt; And my, how his practice has grown!</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013511"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T12:46:48+00:00</published> - <updated>2017-05-02T12:46:48+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.kawa-kun.com,2017-05-02:noticeId=1655658:objectType=note</id> - <title>New note by fortune</title> - <content type="html">There once was a dentist named Stone&lt;br /&gt; Who saw all his patients alone.&lt;br /&gt; In a fit of depravity&lt;br /&gt; He filled the wrong cavity,&lt;br /&gt; And my, how his practice has grown!</content> - <link rel="alternate" type="text/html" href="https://gs.kawa-kun.com/notice/1655658"/> - <status_net notice_id="2013486"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:gs.kawa-kun.com,2017-05-02:noticeId=1655658:objectType=note" href="https://gs.kawa-kun.com/notice/1655658"></thr:in-reply-to> - <link rel="related" href="https://gs.kawa-kun.com/notice/1655658"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034222"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034222" local_id="1034222" ref="https://gs.kawa-kun.com/conversation/714072">https://gs.kawa-kun.com/conversation/714072</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/2013511.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013511.atom"/> - <statusnet:notice_info local_id="2013511" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:note:2013365:2017-05-02T12:37:55+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by xj9: &lt;p&gt;&amp;gt; rollerblading to work&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013394"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T12:37:55+00:00</published> - <updated>2017-05-02T12:37:55+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:sunshinegardens.org,2017-05-02:objectId=61020:objectType=Status</id> - <title>New note by xj9</title> - <content type="html">&lt;p&gt;&amp;gt; rollerblading to work&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://sunshinegardens.org/users/xj9/updates/748"/> - <status_net notice_id="2013365"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:sunshinegardens.org,2017-05-02:objectId=61020:objectType=Status" href="https://sunshinegardens.org/users/xj9/updates/748"></thr:in-reply-to> - <link rel="related" href="https://sunshinegardens.org/users/xj9/updates/748"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034152"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034152" local_id="1034152" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=5a0e98612f634218">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=5a0e98612f634218</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/2013394.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013394.atom"/> - <statusnet:notice_info local_id="2013394" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2013259:2017-05-02T12:29:03+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by cereal: @&lt;a href=&quot;https://gs.smuglo.li/user/28250&quot; class=&quot;h-card mention&quot; title=&quot;Bricky&quot;&gt;thatbrickster&lt;/a&gt; @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; But why?</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013267"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T12:29:03+00:00</published> - <updated>2017-05-02T12:29:03+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:sealion.club,2017-05-02:noticeId=3059985:objectType=comment</id> - <title>New comment by cereal</title> - <content type="html">@&lt;a href=&quot;https://gs.smuglo.li/user/28250&quot; class=&quot;h-card mention&quot; title=&quot;Bricky&quot;&gt;thatbrickster&lt;/a&gt; @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; But why?</content> - <link rel="alternate" type="text/html" href="https://sealion.club/notice/3059985"/> - <status_net notice_id="2013259"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:sealion.club,2017-05-02:noticeId=3059985:objectType=comment" href="https://sealion.club/notice/3059985"></thr:in-reply-to> - <link rel="related" href="https://sealion.club/notice/3059985"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034065"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034065" local_id="1034065" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc</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/2013267.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013267.atom"/> - <statusnet:notice_info local_id="2013267" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2013227:2017-05-02T12:24:27+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by thatbrickster: @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; install gentoo</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013230"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T12:24:27+00:00</published> - <updated>2017-05-02T12:24:27+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:gs.smuglo.li,2017-05-02:noticeId=2144296:objectType=comment</id> - <title>New comment by thatbrickster</title> - <content type="html">@&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; install gentoo</content> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/notice/2144296"/> - <status_net notice_id="2013227"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:gs.smuglo.li,2017-05-02:noticeId=2144296:objectType=comment" href="https://gs.smuglo.li/notice/2144296"></thr:in-reply-to> - <link rel="related" href="https://gs.smuglo.li/notice/2144296"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034065"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034065" local_id="1034065" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc</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/2013230.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013230.atom"/> - <statusnet:notice_info local_id="2013230" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2013213:2017-05-02T12:22:53+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by dwmatiz: @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot;&gt;lambadalambda&lt;/a&gt; *unzips dick*</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013218"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T12:22:53+00:00</published> - <updated>2017-05-02T12:22:53+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:sealion.club,2017-05-02:noticeId=3059800:objectType=comment</id> - <title>New comment by dwmatiz</title> - <content type="html">@&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot;&gt;lambadalambda&lt;/a&gt; *unzips dick*</content> - <link rel="alternate" type="text/html" href="https://sealion.club/notice/3059800"/> - <status_net notice_id="2013213"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:sealion.club,2017-05-02:noticeId=3059800:objectType=comment" href="https://sealion.club/notice/3059800"></thr:in-reply-to> - <link rel="related" href="https://sealion.club/notice/3059800"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034065"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034065" local_id="1034065" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc</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/2013218.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013218.atom"/> - <statusnet:notice_info local_id="2013218" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2013199:2017-05-02T12:22:03+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by shpuld: @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; get #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://shitposter.club/tag/cofe&quot; rel=&quot;tag&quot;&gt;cofe&lt;/a&gt;&lt;/span&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013206"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T12:22:03+00:00</published> - <updated>2017-05-02T12:22:03+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2017-05-02:noticeId=2783524:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; get #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://shitposter.club/tag/cofe&quot; rel=&quot;tag&quot;&gt;cofe&lt;/a&gt;&lt;/span&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2783524"/> - <status_net notice_id="2013199"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-02:noticeId=2783524:objectType=comment" href="https://shitposter.club/notice/2783524"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2783524"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034065"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034065" local_id="1034065" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc</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/2013206.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013206.atom"/> - <statusnet:notice_info local_id="2013206" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-05-02:noticeId=2013185:objectType=note</id> - <title>New note by lambadalambda</title> - <content type="html">What now? &lt;a href=&quot;https://social.heldscal.la/file/e4822d95de677757ff50d49672a4046c83218b76c04a0ad5e5f1f0a9a9eb1a74.gif&quot; title=&quot;https://social.heldscal.la/file/e4822d95de677757ff50d49672a4046c83218b76c04a0ad5e5f1f0a9a9eb1a74.gif&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-422572&quot;&gt;https://social.heldscal.la/attachment/422572&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2013185"/> - <status_net notice_id="2013185"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-02T12:21:04+00:00</published> - <updated>2017-05-02T12:21:04+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1034065"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1034065" local_id="1034065" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2c27c27df8ec4dcc</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" href="https://social.heldscal.la/file/e4822d95de677757ff50d49672a4046c83218b76c04a0ad5e5f1f0a9a9eb1a74.gif" type="image/gif" length="132349"/> - <link rel="self" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013185.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2013185.atom"/> - <statusnet:notice_info local_id="2013185" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:note:2012929:2017-05-02T12:01:25+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by drkmttr: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; I checked out No Agenda because I saw you mention it several time. Sadly, I wasn't impressed. I'm all about varying perspectives but Adam and John basically just sound like resentful curmudgeons. It seems like their shtick is basically playing devil's advocate to everything to arouse some discontent. Just my two cents. 😉&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2012940"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T12:01:25+00:00</published> - <updated>2017-05-02T12:01:25+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:mstdn.io,2017-05-02:objectId=1310093:objectType=Status</id> - <title>New note by drkmttr</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; I checked out No Agenda because I saw you mention it several time. Sadly, I wasn't impressed. I'm all about varying perspectives but Adam and John basically just sound like resentful curmudgeons. It seems like their shtick is basically playing devil's advocate to everything to arouse some discontent. Just my two cents. 😉&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mstdn.io/users/drkmttr/updates/35653"/> - <status_net notice_id="2012929"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:mstdn.io,2017-05-02:objectId=1310093:objectType=Status" href="https://mstdn.io/users/drkmttr/updates/35653"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/users/drkmttr/updates/35653"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1033892"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1033892" local_id="1033892" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2f329b4eb20e83e2">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=2f329b4eb20e83e2</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/2012940.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2012940.atom"/> - <statusnet:notice_info local_id="2012940" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2012336:2017-05-02T11:06:42+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by clacke: @&lt;a href=&quot;https://mastodon.org.uk/users/dick_turpin&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;dick_turpin&quot;&gt;dickturpin&lt;/a&gt; @&lt;a href=&quot;http://quitter.se/user/113503&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Luke&quot;&gt;luke&lt;/a&gt; Oh no, I miss being irritated by you, it helps me understand myself and others. Also it builds character. :-)&lt;br /&gt; &lt;br /&gt; So if this is not federation because you can't follow all of online mankind, what should we call it? Proto-federated? Pre-federated?&lt;br /&gt; &lt;br /&gt; The term has been used decades ago for just one Microsoft Active Directory domain cross-certifying the root of another, by mutual agreement. I don't see how it's any less relevant to opportunistic federation between open servers on an open internet.&lt;br /&gt; &lt;br /&gt; I'm not saying we should be satisfied, I'm just saying that &quot;federate&quot; is a useful word and to build a big system we need to start with a small one. And focus on the things we *can* change, like helping the OStatus network grow and making the tools more useful.&lt;br /&gt; &lt;br /&gt; Saying that the network's ideals have failed because other networks aren't joining is doing neither of that.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2012341"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T11:06:42+00:00</published> - <updated>2017-05-02T11:06:42+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-05-02:noticeId=2012336:objectType=comment</id> - <title>New comment by clacke</title> - <content type="html">@&lt;a href=&quot;https://mastodon.org.uk/users/dick_turpin&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;dick_turpin&quot;&gt;dickturpin&lt;/a&gt; @&lt;a href=&quot;http://quitter.se/user/113503&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Luke&quot;&gt;luke&lt;/a&gt; Oh no, I miss being irritated by you, it helps me understand myself and others. Also it builds character. :-)&lt;br /&gt; &lt;br /&gt; So if this is not federation because you can't follow all of online mankind, what should we call it? Proto-federated? Pre-federated?&lt;br /&gt; &lt;br /&gt; The term has been used decades ago for just one Microsoft Active Directory domain cross-certifying the root of another, by mutual agreement. I don't see how it's any less relevant to opportunistic federation between open servers on an open internet.&lt;br /&gt; &lt;br /&gt; I'm not saying we should be satisfied, I'm just saying that &amp;quot;federate&amp;quot; is a useful word and to build a big system we need to start with a small one. And focus on the things we *can* change, like helping the OStatus network grow and making the tools more useful.&lt;br /&gt; &lt;br /&gt; Saying that the network's ideals have failed because other networks aren't joining is doing neither of that.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2012336"/> - <status_net notice_id="2012336"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:social.heldscal.la,2017-05-02:noticeId=2012336:objectType=comment" href="https://social.heldscal.la/notice/2012336"></thr:in-reply-to> - <link rel="related" href="https://social.heldscal.la/notice/2012336"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1016421"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1016421" local_id="1016421" ref="https://s.wefamlee.be/conversation/16478">https://s.wefamlee.be/conversation/16478</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/2012341.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2012341.atom"/> - <statusnet:notice_info local_id="2012341" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-02:fave:23211:comment:2011332:2017-05-02T10:37:40+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by moonman: @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=mKLizztikRk&quot; title=&quot;https://www.youtube.com/watch?v=mKLizztikRk&quot; class=&quot;attachment&quot; rel=&quot;nofollow&quot;&gt;https://www.youtube.com/watch?v=mKLizztikRk&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2012148"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-02T10:37:40+00:00</published> - <updated>2017-05-02T10:37:40+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2017-05-02:noticeId=2781833:objectType=comment</id> - <title>New comment by moonman</title> - <content type="html">@&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=mKLizztikRk&quot; title=&quot;https://www.youtube.com/watch?v=mKLizztikRk&quot; class=&quot;attachment&quot; rel=&quot;nofollow&quot;&gt;https://www.youtube.com/watch?v=mKLizztikRk&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2781833"/> - <status_net notice_id="2011332"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-02:noticeId=2781833:objectType=comment" href="https://shitposter.club/notice/2781833"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2781833"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1032783"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1032783" local_id="1032783" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=11d8b8c27d9513ec">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=11d8b8c27d9513ec</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/2012148.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2012148.atom"/> - <statusnet:notice_info local_id="2012148" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-05-02:noticeId=2012145:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://sealion.club/user/186&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;I'M CEREAL U GUISE&quot;&gt;cereal&lt;/a&gt; ? No, you don't even need the identity servers for federation.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2012145"/> - <status_net notice_id="2012145"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-02T10:37:33+00:00</published> - <updated>2017-05-02T10:37:33+00:00</updated> - <thr:in-reply-to ref="tag:sealion.club,2017-05-02:noticeId=3056001:objectType=comment" href="https://sealion.club/notice/3056001"></thr:in-reply-to> - <link rel="related" href="https://sealion.club/notice/3056001"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1033277"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1033277" local_id="1033277" ref="https://sealion.club/conversation/1629037">https://sealion.club/conversation/1629037</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://sealion.club/user/186"/> - <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/2012145.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2012145.atom"/> - <statusnet:notice_info local_id="2012145" source="Pleroma FE"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/custom_instance_panel.html b/test/fixtures/custom_instance_panel.html @@ -0,0 +1 @@ +<h2>Custom instance panel</h2> +\ No newline at end of file diff --git a/test/fixtures/cw_retweet.xml b/test/fixtures/cw_retweet.xml @@ -1,68 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://mastodon.social/users/lambadalambda.atom</id> - <title>Critical Value</title> - <subtitle></subtitle> - <updated>2017-04-16T21:47:25Z</updated> - <logo>https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif</logo> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda.atom"/> - <link rel="hub" href="https://mastodon.social/api/push"/> - <link rel="salmon" href="https://mastodon.social/api/salmon/264"/> - <entry> - <id>tag:mastodon.social,2017-05-11:objectId=5647963:objectType=Status</id> - <published>2017-05-11T10:23:15Z</published> - <updated>2017-05-11T10:23:15Z</updated> - <title>lambadalambda shared a status by Skruyb@mamot.fr</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:mamot.fr,2017-05-10:objectId=1294943:objectType=Status</id> - <published>2017-05-10T17:31:44Z</published> - <updated>2017-05-10T17:31:45Z</updated> - <title>New status by Skruyb@mamot.fr</title> - <author> - <id>https://mamot.fr/users/Skruyb</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mamot.fr/users/Skruyb</uri> - <name>Skruyb</name> - <email>Skruyb@mamot.fr</email> - <summary type="html">&lt;p&gt;Fr and En.&lt;br&gt;Posts will disappear on a regular basis.&lt;/p&gt;</summary> - <link rel="alternate" type="text/html" href="https://mamot.fr/@Skruyb"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/106/282/original/d95dbcfc76f77f4c.jpg"/> - <link rel="header" type="image/jpeg" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/106/282/original/c1aabdf5c97eb875.jpg"/> - <poco:preferredUsername>Skruyb</poco:preferredUsername> - <poco:displayName>The 7th Son</poco:displayName> - <poco:note>Fr and En.Posts will disappear on a regular basis.</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <summary xml:lang="it">Hey.</summary> - <content type="html" xml:lang="it">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@lambadalambda"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Hey!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/lambadalambda"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176041"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-05-10:objectId=5582979:objectType=Status" href="https://mastodon.social/@lambadalambda/5582979"/> - </activity:object> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@lambadalambda"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Hey!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2325225"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2325225.atom"/> - </entry> -</feed> diff --git a/test/fixtures/delete.xml b/test/fixtures/delete.xml @@ -1,39 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://mastodon.sdf.org/users/snowdusk.atom</id> - <title>snowdusk</title> - <subtitle>Amateur live performance DJ/radio DJ on SDF's underground Internet radio http://aNONradio.net (LIVE Sat Sun Mon Tue 23:00-24:00 UTC) - http://snowdusk.sdf.org</subtitle> - <updated>2017-06-17T04:14:34Z</updated> - <logo>https://mastodon.sdf.org/system/accounts/avatars/000/000/002/original/405a7652d5f60449.jpg?1497672873</logo> - <author> - <id>https://mastodon.sdf.org/users/snowdusk</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.sdf.org/users/snowdusk</uri> - <name>snowdusk</name> - <email>snowdusk@mastodon.sdf.org</email> - <summary type="html">&lt;p&gt;Amateur live performance DJ/radio DJ on SDF&amp;apos;s underground Internet radio &lt;a href="http://anonradio.net/" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;http://&lt;/span&gt;&lt;span class=""&gt;anonradio.net/&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt; (LIVE Sat Sun Mon Tue 23:00-24:00 UTC) - &lt;a href="http://snowdusk.sdf.org/" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;http://&lt;/span&gt;&lt;span class=""&gt;snowdusk.sdf.org/&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</summary> - <link rel="alternate" type="text/html" href="https://mastodon.sdf.org/@snowdusk"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://mastodon.sdf.org/system/accounts/avatars/000/000/002/original/405a7652d5f60449.jpg?1497672873"/> - <link rel="header" type="image/jpeg" media:width="700" media:height="335" href="https://mastodon.sdf.org/system/accounts/headers/000/000/002/original/f1e9b0fb21b4e5a0.jpeg?1495793472"/> - <poco:preferredUsername>snowdusk</poco:preferredUsername> - <poco:displayName>snowdusk</poco:displayName> - <poco:note>Amateur live performance DJ/radio DJ on SDF's underground Internet radio http://aNONradio.net (LIVE Sat Sun Mon Tue 23:00-24:00 UTC) - http://snowdusk.sdf.org</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://mastodon.sdf.org/@snowdusk"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.sdf.org/users/snowdusk.atom"/> - <link rel="next" type="application/atom+xml" href="https://mastodon.sdf.org/users/snowdusk.atom?max_id=7592"/> - <link rel="hub" href="https://mastodon.sdf.org/api/push"/> - <link rel="salmon" href="https://mastodon.sdf.org/api/salmon/2"/> - <entry> - <id>tag:mastodon.sdf.org,2017-06-10:objectId=310513:objectType=Status</id> - <published>2017-06-10T22:02:31Z</published> - <updated>2017-06-10T22:02:31Z</updated> - <title>snowdusk deleted status</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/delete</activity:verb> - <content>Deleted status</content> - <link rel="alternate" type="text/html" href="https://mastodon.sdf.org/users/snowdusk/updates/7782"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.sdf.org/users/snowdusk/updates/7782.atom"/> - </entry> -</feed> diff --git a/test/fixtures/dm.xml b/test/fixtures/dm.xml @@ -1,27 +0,0 @@ -<?xml version="1.0"?> -<entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>tag:mastodon.social,2017-06-30:objectId=11260427:objectType=Status</id> - <published>2017-06-30T13:27:47Z</published> - <updated>2017-06-30T13:27:47Z</updated> - <title>New status by lambadalambda</title> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="ky">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Hey.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <mastodon:scope>direct</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/3514345"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/3514345.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2017-06-30:objectId=4009714:objectType=Conversation"/> -</entry> diff --git a/test/fixtures/favorite.xml b/test/fixtures/favorite.xml @@ -1,65 +0,0 @@ -<?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> diff --git a/test/fixtures/favorite_with_local_note.xml b/test/fixtures/favorite_with_local_note.xml @@ -1,64 +0,0 @@ -<?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>localid</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> - <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> diff --git a/test/fixtures/follow.xml b/test/fixtures/follow.xml @@ -1,68 +0,0 @@ -<?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-07T09:54:49+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-07:subscription:23211:person:44803:2017-05-07T09:54:48+00:00</id> - <title>Constance Variable (lambadalambda@social.heldscal.la)'s status on Sunday, 07-May-2017 09:54:49 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot;&gt;Constance Variable&lt;/a&gt; started following &lt;a href=&quot;https://pawoo.net/@pekorino&quot;&gt;mono&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2092981"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-05-07T09:54:49+00:00</published> - <updated>2017-05-07T09:54:49+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://pawoo.net/users/pekorino</id> - <title>mono</title> - <summary>http://shitposter.club/mono 孤独のグルメ</summary> - <link rel="alternate" type="text/html" href="https://pawoo.net/@pekorino"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://social.heldscal.la/theme/neo-gnu/default-avatar-profile.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://social.heldscal.la/theme/neo-gnu/default-avatar-stream.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://social.heldscal.la/theme/neo-gnu/default-avatar-mini.png"/> - <poco:preferredUsername>pekorino</poco:preferredUsername> - <poco:displayName>mono</poco:displayName> - <poco:note>http://shitposter.club/mono 孤独のグルメ</poco:note> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1079786"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1079786" local_id="1079786" ref="tag:social.heldscal.la,2017-05-07:objectType=thread:nonce=6e80caf94e03029f">tag:social.heldscal.la,2017-05-07:objectType=thread:nonce=6e80caf94e03029f</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/2092981.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2092981.atom"/> - <statusnet:notice_info local_id="2092981" source="activity"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/image.gif b/test/fixtures/image.gif Binary files differ. diff --git a/test/fixtures/image.png b/test/fixtures/image.png Binary files differ. diff --git a/test/fixtures/incoming_note_activity.xml b/test/fixtures/incoming_note_activity.xml @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?><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/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-23:noticeId=29:objectType=note</id> - <title>New note by lambda</title> - <content type="html">@&lt;a href=&quot;http://pleroma.example.org:4000/users/lain3&quot; class=&quot;h-card mention&quot;&gt;lain3&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="http://gs.example.org:4040/index.php/notice/29"/> - <link name="marko" rel="emoji" href="marko.png" /> - <link name="reimu" rel="emoji" href="reimu.png" /> - <status_net notice_id="29"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-23T14:51:03+00:00</published> - <updated>2017-04-23T14:51:03+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>http://gs.example.org:4040/index.php/user/1</uri> - <name>lambda</name> - <link rel="alternate" type="text/html" href="http://gs.example.org:4040/index.php/lambda"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://gs.example.org:4040/theme/neo-gnu/default-avatar-profile.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://gs.example.org:4040/theme/neo-gnu/default-avatar-stream.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://gs.example.org:4040/theme/neo-gnu/default-avatar-mini.png"/> - <poco:preferredUsername>lambda</poco:preferredUsername> - <poco:displayName>lambda</poco:displayName> - <followers url="http://gs.example.org:4040/index.php/lambda/subscribers"></followers> - <statusnet:profile_info local_id="1"></statusnet:profile_info> - </author> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-23:objectType=thread:nonce=f09e22f58abd5c7b"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-23:objectType=thread:nonce=f09e22f58abd5c7b</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain3"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>http://gs.example.org:4040/index.php/api/statuses/user_timeline/1.atom</id> - <title>lambda</title> - <link rel="alternate" type="text/html" href="http://gs.example.org:4040/index.php/lambda"/> - <link rel="self" type="application/atom+xml" href="http://gs.example.org:4040/index.php/api/statuses/user_timeline/1.atom"/> - <link rel="license" href="https://creativecommons.org/licenses/by/3.0/"/> - <icon>http://gs.example.org:4040/theme/neo-gnu/default-avatar-profile.png</icon> - <updated>2017-04-23T14:51:03+00:00</updated> - </source> - <link rel="self" type="application/atom+xml" href="http://gs.example.org:4040/index.php/api/statuses/show/29.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org:4040/index.php/api/statuses/show/29.atom"/> - <statusnet:notice_info local_id="29" source="web"></statusnet:notice_info> -</entry> diff --git a/test/fixtures/incoming_note_activity_answer.xml b/test/fixtures/incoming_note_activity_answer.xml @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?><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/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=55:objectType=note</id> - <title>New note by lambda</title> - <content type="html">hey.</content> - <link rel="alternate" type="text/html" href="http://gs.example.org:4040/index.php/notice/55"/> - <status_net notice_id="55"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T18:16:13+00:00</published> - <updated>2017-04-25T18:16:13+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>http://gs.example.org:4040/index.php/user/1</uri> - <name>lambda</name> - <link rel="alternate" type="text/html" href="http://gs.example.org:4040/index.php/lambda"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://gs.example.org:4040/theme/neo-gnu/default-avatar-profile.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://gs.example.org:4040/theme/neo-gnu/default-avatar-stream.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://gs.example.org:4040/theme/neo-gnu/default-avatar-mini.png"/> - <poco:preferredUsername>lambda</poco:preferredUsername> - <poco:displayName>lambda</poco:displayName> - <followers url="http://gs.example.org:4040/index.php/lambda/subscribers"></followers> - <statusnet:profile_info local_id="1"></statusnet:profile_info> - </author> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/55bce8fc-b423-46b1-af71-3759ab4670bc" href="http://pleroma.example.org:4000/objects/55bce8fc-b423-46b1-af71-3759ab4670bc"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/55bce8fc-b423-46b1-af71-3759ab4670bc"/> - <link rel="ostatus:conversation" href="http://pleroma.example.org:4000/contexts/8f6f45d4-8e4d-4e1a-a2de-09f27367d2d0"/> - <ostatus:conversation>http://pleroma.example.org:4000/contexts/8f6f45d4-8e4d-4e1a-a2de-09f27367d2d0</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>http://gs.example.org:4040/index.php/api/statuses/user_timeline/1.atom</id> - <title>lambda</title> - <link rel="alternate" type="text/html" href="http://gs.example.org:4040/index.php/lambda"/> - <link rel="self" type="application/atom+xml" href="http://gs.example.org:4040/index.php/api/statuses/user_timeline/1.atom"/> - <link rel="license" href="https://creativecommons.org/licenses/by/3.0/"/> - <icon>http://gs.example.org:4040/theme/neo-gnu/default-avatar-profile.png</icon> - <updated>2017-04-25T18:16:13+00:00</updated> - </source> - <link rel="self" type="application/atom+xml" href="http://gs.example.org:4040/index.php/api/statuses/show/55.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org:4040/index.php/api/statuses/show/55.atom"/> - <statusnet:notice_info local_id="55" source="web"></statusnet:notice_info> -</entry> diff --git a/test/fixtures/incoming_reply_mastodon.xml b/test/fixtures/incoming_reply_mastodon.xml @@ -1,29 +0,0 @@ -<?xml version="1.0"?> -<entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>tag:mastodon.social,2017-05-02:objectId=4901603:objectType=Status</id> - <published>2017-05-02T18:33:06Z</published> - <updated>2017-05-02T18:33:06Z</updated> - <title>New status by lambadalambda</title> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="el">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; hey&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2224923"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2224923.atom"/> - <thr:in-reply-to ref="https://pleroma.soykaf.com/objects/c237d966-ac75-4fe3-a87a-d89d71a3a7a4" href=""/> -</entry> diff --git a/test/fixtures/incoming_websub_gnusocial_attachments.xml b/test/fixtures/incoming_websub_gnusocial_attachments.xml @@ -1,59 +0,0 @@ -<?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-02T20:29:35+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> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-05-02:noticeId=2020923:objectType=note</id> - <title>New note by lambadalambda</title> - <content type="html">Okay gonna stream some cool games!! &lt;a href=&quot;https://social.heldscal.la/file/7ed5ee508e6376a6e3dd581e17e7ed0b7b638147c7e86784bf83abc2641ee3d4.gif&quot; title=&quot;https://social.heldscal.la/file/7ed5ee508e6376a6e3dd581e17e7ed0b7b638147c7e86784bf83abc2641ee3d4.gif&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-423842&quot;&gt;https://social.heldscal.la/attachment/423842&lt;/a&gt; &lt;a href=&quot;https://social.heldscal.la/file/4c209099cadfc5afd3e27a334aa0db96b3a7510dde1603305d68a2707e59a11f.png&quot; title=&quot;https://social.heldscal.la/file/4c209099cadfc5afd3e27a334aa0db96b3a7510dde1603305d68a2707e59a11f.png&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-423843&quot;&gt;https://social.heldscal.la/attachment/423843&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2020923"/> - <status_net notice_id="2020923"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-02T20:29:35+00:00</published> - <updated>2017-05-02T20:29:35+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1038558"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1038558" local_id="1038558" ref="tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=26c7afdcbcf4ebd4">tag:social.heldscal.la,2017-05-02:objectType=thread:nonce=26c7afdcbcf4ebd4</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" href="https://social.heldscal.la/file/7ed5ee508e6376a6e3dd581e17e7ed0b7b638147c7e86784bf83abc2641ee3d4.gif" type="image/gif" length="17283"/> - <link rel="enclosure" href="https://social.heldscal.la/file/4c209099cadfc5afd3e27a334aa0db96b3a7510dde1603305d68a2707e59a11f.png" type="image/png" length="6965"/> - <link rel="self" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2020923.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2020923.atom"/> - <statusnet:notice_info local_id="2020923" source="Pleroma FE"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/lambadalambda.atom b/test/fixtures/lambadalambda.atom @@ -1,479 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://mastodon.social/users/lambadalambda.atom</id> - <title>Critical Value</title> - <subtitle></subtitle> - <updated>2017-04-16T21:47:25Z</updated> - <logo>https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif?1492379244</logo> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <summary>a cool dude.</summary> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif?1492379244"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda.atom"/> - <link rel="next" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda.atom?max_id=1488609"/> - <link rel="hub" href="https://mastodon.social/api/push"/> - <link rel="salmon" href="https://mastodon.social/api/salmon/264"/> - <entry> - <id>tag:mastodon.social,2017-04-07:objectId=1874242:objectType=Status</id> - <published>2017-04-07T11:02:56Z</published> - <updated>2017-04-07T11:02:56Z</updated> - <title>lambadalambda shared a status by 0xroy@social.wxcafe.net</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:social.wxcafe.net,2017-04-07:objectId=72554:objectType=Status</id> - <published>2017-04-07T11:01:59Z</published> - <updated>2017-04-07T11:02:00Z</updated> - <title>New status by 0xroy@social.wxcafe.net</title> - <author> - <id>https://social.wxcafe.net/users/0xroy</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://social.wxcafe.net/users/0xroy</uri> - <name>0xroy</name> - <email>0xroy@social.wxcafe.net</email> - <summary>ta caution weeb | discussions privées : &lt;a href="https://💌.0xroy.me" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class=""&gt;💌.0xroy.me&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;</summary> - <link rel="alternate" type="text/html" href="https://social.wxcafe.net/@0xroy"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/036/953/original/20068e41d0310172.jpg?1491240516"/> - <link rel="header" type="image/jpeg" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/036/953/original/2229d0e3f129fe8c.jpg?1491381114"/> - <poco:preferredUsername>0xroy</poco:preferredUsername> - <poco:displayName>「R O Y 🍵 B O S」</poco:displayName> - <poco:note>ta caution weeb | discussions privées : &lt;a href="https://%F0%9F%92%8C.0xroy.me" rel="nofollow noopener"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class=""&gt;💌.0xroy.me&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;someone pls eli5 matrix (protocol) and riot&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://social.wxcafe.net/users/0xroy/updates/4510"/> - </activity:object> - <content type="html" xml:lang="en">&lt;p&gt;someone pls eli5 matrix (protocol) and riot&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1689208"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1689208.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-06:objectId=1768247:objectType=Status</id> - <published>2017-04-06T11:10:19Z</published> - <updated>2017-04-06T11:10:19Z</updated> - <title>lambadalambda shared a status by areyoutoo@mastodon.xyz</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:mastodon.xyz,2017-04-05:objectId=133327:objectType=Status</id> - <published>2017-04-05T17:36:41Z</published> - <updated>2017-04-05T18:12:14Z</updated> - <title>New status by areyoutoo@mastodon.xyz</title> - <author> - <id>https://mastodon.xyz/users/areyoutoo</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.xyz/users/areyoutoo</uri> - <name>areyoutoo</name> - <email>areyoutoo@mastodon.xyz</email> - <summary>devops | retired gamedev | always boost puppy pics</summary> - <link rel="alternate" type="text/html" href="https://mastodon.xyz/@areyoutoo"/> - <link rel="avatar" type="image/png" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/047/888/original/5ce2e132d4c18d65.png?1491343828"/> - <link rel="header" type="image/png" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/047/888/original/missing.png?1491336769"/> - <poco:preferredUsername>areyoutoo</poco:preferredUsername> - <poco:displayName>Raw Butter</poco:displayName> - <poco:note>devops | retired gamedev | always boost puppy pics</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;Some UX thoughts for &lt;a href="https://mastodon.xyz/tags/mastodev" class="mention hashtag"&gt;#&lt;span&gt;mastodev&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;- Would be nice if I could work on multiple draft toots? Clicking to reply to someone seems to erase any draft I had been working on.&lt;/p&gt;&lt;p&gt;- Kinda risky to click on the Federated Timeline if it loads new toots and scrolls 10ms before I click on something.&lt;/p&gt;&lt;p&gt;I probably don't know enough web frontend to help, but it might be fun to try.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="mastodev"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.xyz/users/areyoutoo/updates/36028"/> - </activity:object> - <content type="html" xml:lang="en">&lt;p&gt;Some UX thoughts for &lt;a href="https://mastodon.xyz/tags/mastodev" class="mention hashtag"&gt;#&lt;span&gt;mastodev&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;- Would be nice if I could work on multiple draft toots? Clicking to reply to someone seems to erase any draft I had been working on.&lt;/p&gt;&lt;p&gt;- Kinda risky to click on the Federated Timeline if it loads new toots and scrolls 10ms before I click on something.&lt;/p&gt;&lt;p&gt;I probably don't know enough web frontend to help, but it might be fun to try.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1658950"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1658950.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-06:objectId=1764509:objectType=Status</id> - <published>2017-04-06T10:15:38Z</published> - <updated>2017-04-06T10:15:38Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <summary xml:lang="en">This is a test for cw federation</summary> - <content type="html" xml:lang="en">&lt;p&gt;This is a test for cw federation body text.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1657819"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1657819.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-05:objectId=1645208:objectType=Status</id> - <published>2017-04-05T07:14:53Z</published> - <updated>2017-04-05T07:14:53Z</updated> - <title>lambadalambda shared a status by lambadalambda@social.heldscal.la</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:social.heldscal.la,2017-04-05:noticeId=1502088:objectType=note</id> - <published>2017-04-05T06:12:09Z</published> - <updated>2017-04-05T07:12:47Z</updated> - <title>New status by lambadalambda@social.heldscal.la</title> - <author> - <id>https://social.heldscal.la/user/23211</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://social.heldscal.la/user/23211</uri> - <name>lambadalambda</name> - <email>lambadalambda@social.heldscal.la</email> - <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="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/236/original/23211-original-20170416114255.jpeg?1492345317"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Constance Variable</poco:displayName> - <poco:note>Call me Deacon Blues.</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">Federation 101: &lt;a href="https://www.youtube.com/watch?v=t1lYU5CA40o" rel="nofollow external noreferrer" class="attachment thumbnail"&gt;https://www.youtube.com/watch?v=t1lYU5CA40o&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1502088"/> - </activity:object> - <content type="html" xml:lang="en">Federation 101: &lt;a href="https://www.youtube.com/watch?v=t1lYU5CA40o" rel="nofollow external noreferrer" class="attachment thumbnail"&gt;https://www.youtube.com/watch?v=t1lYU5CA40o&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1618003"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1618003.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-05:objectId=1641750:objectType=Status</id> - <published>2017-04-05T05:44:48Z</published> - <updated>2017-04-05T05:44:48Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://social.heldscal.la/lambadalambda" class="u-url mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; just a test.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/23211"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1616358"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1616358.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-04:objectId=1540149:objectType=Status</id> - <published>2017-04-04T06:31:09Z</published> - <updated>2017-04-04T06:31:09Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;Looks like you still can&amp;apos;t delete your account here (PRIVACY!), but I won&amp;apos;t be posting here anymore, my main account is &lt;span class="h-card"&gt;&lt;a href="https://social.heldscal.la/lambadalambda" class="u-url mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/23211"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1559641"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1559641.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-04:objectId=1539608:objectType=Status</id> - <published>2017-04-04T06:18:16Z</published> - <updated>2017-04-04T06:18:16Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@ghostbar" class="u-url mention"&gt;@&lt;span&gt;ghostbar&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Remember to rewrite it in Rust once you&amp;apos;re done.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/ghostbar"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1559263"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1559263.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-03:objectId=1514426:objectType=Status" href="https://mastodon.social/@ghostbar/1514426"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1504813:objectType=Status</id> - <published>2017-04-03T18:01:20Z</published> - <updated>2017-04-03T18:01:20Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.xyz/@Azurolu" class="u-url mention"&gt;@&lt;span&gt;Azurolu&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; You mean gs.smuglo.li?&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.xyz/users/Azurolu"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1535844"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1535844.atom"/> - <thr:in-reply-to ref="tag:mastodon.xyz,2017-04-03:objectId=21879:objectType=Status" href="https://mastodon.xyz/users/Azurolu/updates/3813"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1504805:objectType=Status</id> - <published>2017-04-03T18:01:05Z</published> - <updated>2017-04-03T18:01:05Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;There&amp;apos;s nothing wrong with having several alt accounts all across the fediverse. Try out another mastodon instance (&lt;a href="https://icosahedron.website" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class=""&gt;icosahedron.website&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;) or a GNU Social instance (like &lt;a href="https://shitposter.club" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class=""&gt;shitposter.club&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt; or &lt;a href="https://freezepeach.xyz" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class=""&gt;freezepeach.xyz&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;), or friendica. They are all on the same network, so you can still follow all your friends!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1535837"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1535837.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1503965:objectType=Status</id> - <published>2017-04-03T17:31:30Z</published> - <updated>2017-04-03T17:31:30Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@20Hz" class="u-url mention"&gt;@&lt;span&gt;20Hz&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; you could also try out a GS instance, which are on the same network :)&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/20Hz"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1535176"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1535176.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-03:objectId=1503524:objectType=Status" href="https://mastodon.social/@20Hz/1503524"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1503955:objectType=Status</id> - <published>2017-04-03T17:31:08Z</published> - <updated>2017-04-03T17:31:08Z</updated> - <title>lambadalambda shared a status by shpuld@shitposter.club</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:shitposter.club,2017-04-03:noticeId=2251717:objectType=note</id> - <published>2017-04-03T17:06:43Z</published> - <updated>2017-04-03T17:12:06Z</updated> - <title>New status by shpuld@shitposter.club</title> - <author> - <id>https://shitposter.club/user/5381</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://shitposter.club/user/5381</uri> - <name>shpuld</name> - <email>shpuld@shitposter.club</email> - <summary></summary> - <link rel="alternate" type="text/html" href="https://shitposter.club/shpuld"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/005/895/original/5381-original-20170401213417.jpeg?1491082522"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>shpuld</poco:preferredUsername> - <poco:displayName>shp</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">reposting the classic &lt;a href="https://shitposter.club/file/89c5fe483526caf3a46cfc5cdd4ae68061054350e767397731af658d54786e31.jpg" class="attachment" rel="nofollow external"&gt;https://shitposter.club/attachment/219846&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" type="image/jpeg" length="30588" href="https://files.mastodon.social/media_attachments/files/000/156/256/original/89c5fe483526caf3a46cfc5cdd4ae68061054350e767397731af658d54786e31.jpg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2251717"/> - </activity:object> - <content type="html" xml:lang="en">reposting the classic &lt;a href="https://shitposter.club/file/89c5fe483526caf3a46cfc5cdd4ae68061054350e767397731af658d54786e31.jpg" class="attachment" rel="nofollow external"&gt;https://shitposter.club/attachment/219846&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1535166"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1535166.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1503929:objectType=Status</id> - <published>2017-04-03T17:30:43Z</published> - <updated>2017-04-03T17:30:43Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@ghostbar" class="u-url mention"&gt;@&lt;span&gt;ghostbar&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Normally you shouldn&amp;apos;t be running tens of thousands of users on one instance... That&amp;apos;s one of the reasons for federation.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/ghostbar"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1535144"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1535144.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-03:objectId=1503526:objectType=Status" href="https://mastodon.social/@ghostbar/1503526"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1477255:objectType=Status</id> - <published>2017-04-03T08:24:39Z</published> - <updated>2017-04-03T08:24:39Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@dot_tiff" class="u-url mention"&gt;@&lt;span&gt;dot_tiff&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; it&amp;apos;s the vaporwave mode.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/dot_tiff"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1513305"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1513305.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-03:objectId=1477220:objectType=Status" href="https://mastodon.social/@dot_tiff/1477220"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1476210:objectType=Status</id> - <published>2017-04-03T07:45:42Z</published> - <updated>2017-04-03T07:45:42Z</updated> - <title>lambadalambda shared a status by lambadalambda@social.heldscal.la</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:social.heldscal.la,2017-04-03:noticeId=1475727:objectType=note</id> - <published>2017-04-03T07:44:43Z</published> - <updated>2017-04-03T07:44:48Z</updated> - <title>New status by lambadalambda@social.heldscal.la</title> - <author> - <id>https://social.heldscal.la/user/23211</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://social.heldscal.la/user/23211</uri> - <name>lambadalambda</name> - <email>lambadalambda@social.heldscal.la</email> - <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="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/236/original/23211-original-20170416114255.jpeg?1492345317"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Constance Variable</poco:displayName> - <poco:note>Call me Deacon Blues.</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">Here's a song by the original anti-idol, Togawa Jun: &lt;a href="https://www.youtube.com/watch?v=kNI_NK2YY-s" rel="nofollow external noreferrer" class="attachment"&gt;https://www.youtube.com/watch?v=kNI_NK2YY-s&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1475727"/> - </activity:object> - <content type="html" xml:lang="en">Here's a song by the original anti-idol, Togawa Jun: &lt;a href="https://www.youtube.com/watch?v=kNI_NK2YY-s" rel="nofollow external noreferrer" class="attachment"&gt;https://www.youtube.com/watch?v=kNI_NK2YY-s&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1512485"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1512485.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1476047:objectType=Status</id> - <published>2017-04-03T07:39:14Z</published> - <updated>2017-04-03T07:39:14Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@amrrr" class="u-url mention"&gt;@&lt;span&gt;amrrr&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; tumblr/10, but pretty good!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/amrrr"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1512350"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1512350.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-03:objectId=1476030:objectType=Status" href="https://mastodon.social/@amrrr/1476030"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1475949:objectType=Status</id> - <published>2017-04-03T07:35:45Z</published> - <updated>2017-04-03T07:35:45Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@Shookaite" class="u-url mention"&gt;@&lt;span&gt;Shookaite&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Oh, you mean like userstyles?&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/Shookaite"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1512271"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1512271.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-03:objectId=1475879:objectType=Status" href="https://mastodon.social/@Shookaite/1475879"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-03:objectId=1475581:objectType=Status</id> - <published>2017-04-03T07:20:03Z</published> - <updated>2017-04-03T07:20:03Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@Shookaite" class="u-url mention"&gt;@&lt;span&gt;Shookaite&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Would be nice if someone helped port Pleroma to Mastodon, that has a theme switcher (click on the cog in the upper right): &lt;a href="https://pleroma.heldscal.la/main/all" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class=""&gt;pleroma.heldscal.la/main/all&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/Shookaite"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1511987"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1511987.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-03:objectId=1475550:objectType=Status" href="https://mastodon.social/@Shookaite/1475550"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-02:objectId=1457325:objectType=Status</id> - <published>2017-04-02T21:57:43Z</published> - <updated>2017-04-02T21:57:43Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@rhosyn" class="u-url mention"&gt;@&lt;span&gt;rhosyn&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@Meaningness" class="u-url mention"&gt;@&lt;span&gt;Meaningness&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; you could take a look at those listed at social.guhnoo.org&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/rhosyn"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/Meaningness"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1496564"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1496564.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-02:objectId=1449283:objectType=Status" href="https://mastodon.social/@rhosyn/1449283"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-02:objectId=1447926:objectType=Status</id> - <published>2017-04-02T18:31:52Z</published> - <updated>2017-04-02T18:31:52Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;My main account is &lt;span class="h-card"&gt;&lt;a href="https://social.heldscal.la/lambadalambda" class="u-url mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; , btw.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/23211"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1488648"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1488648.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-02:objectId=1447878:objectType=Status</id> - <published>2017-04-02T18:30:37Z</published> - <updated>2017-04-02T18:30:37Z</updated> - <title>lambadalambda shared a status by Firstaide@awoo.space</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:awoo.space,2017-04-02:objectId=135324:objectType=Status</id> - <published>2017-04-02T18:29:32Z</published> - <updated>2017-04-02T18:29:32Z</updated> - <title>New status by Firstaide@awoo.space</title> - <author> - <id>https://awoo.space/users/Firstaide</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://awoo.space/users/Firstaide</uri> - <name>Firstaide</name> - <email>Firstaide@awoo.space</email> - <summary>A smol awoo account, for a smol autistic 💙 -They/them please! -NB/white/ace</summary> - <link rel="alternate" type="text/html" href="https://awoo.space/@Firstaide"/> - <link rel="avatar" type="image/png" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/023/707/original/95e92639771fd225.png?1492022811"/> - <link rel="header" type="image/jpeg" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/023/707/original/e98df174c26747be.jpg?1491667928"/> - <poco:preferredUsername>Firstaide</poco:preferredUsername> - <poco:displayName>Miff🚑✨</poco:displayName> - <poco:note>A smol awoo account, for a smol autistic 💙 -They/them please! -NB/white/ace</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;a href="https://mastodon.social/users/lambadalambda" class="h-card u-url p-nickname mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt; yeah, I think that's p much the big issue here? &lt;br&gt;When I first heard of Masto, I thought it was just like twitter at first, I had no idea federation was even a thing?, and I actually joined p early on? :-o &lt;/p&gt;&lt;p&gt;idk I think more stuff needs to be done about federation promotion, but honestly its gotta come from the get go when people get here to make an account I feel :-o&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/lambadalambda"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://awoo.space/users/Firstaide/updates/10904"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-04-02:objectId=1447682:objectType=Status" href="https://mastodon.social/@lambadalambda/1447682"/> - </activity:object> - <content type="html" xml:lang="en">&lt;p&gt;&lt;a href="https://mastodon.social/users/lambadalambda" class="h-card u-url p-nickname mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt; yeah, I think that's p much the big issue here? &lt;br&gt;When I first heard of Masto, I thought it was just like twitter at first, I had no idea federation was even a thing?, and I actually joined p early on? :-o &lt;/p&gt;&lt;p&gt;idk I think more stuff needs to be done about federation promotion, but honestly its gotta come from the get go when people get here to make an account I feel :-o&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1488609"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1488609.atom"/> - </entry> -</feed> diff --git a/test/fixtures/mastodon-note-cw.xml b/test/fixtures/mastodon-note-cw.xml @@ -1,39 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://mastodon.social/users/lambadalambda.atom</id> - <title>Critical Value</title> - <subtitle></subtitle> - <updated>2017-04-16T21:47:25Z</updated> - <logo>https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif</logo> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda.atom"/> - <link rel="hub" href="https://mastodon.social/api/push"/> - <link rel="salmon" href="https://mastodon.social/api/salmon/264"/> - <entry> - <id>tag:mastodon.social,2017-05-10:objectId=5551985:objectType=Status</id> - <published>2017-05-10T12:21:36Z</published> - <updated>2017-05-10T12:21:36Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <summary xml:lang="sv">technologic</summary> - <content type="html" xml:lang="sv">&lt;p&gt;test&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2314748"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2314748.atom"/> - </entry> -</feed> diff --git a/test/fixtures/mastodon-note-unlisted.xml b/test/fixtures/mastodon-note-unlisted.xml @@ -1,38 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://mastodon.social/users/lambadalambda.atom</id> - <title>Critical Value</title> - <subtitle></subtitle> - <updated>2017-04-16T21:47:25Z</updated> - <logo>https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif</logo> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda.atom"/> - <link rel="hub" href="https://mastodon.social/api/push"/> - <link rel="salmon" href="https://mastodon.social/api/salmon/264"/> - <entry> - <id>tag:mastodon.social,2017-05-10:objectId=5551985:objectType=Status</id> - <published>2017-05-10T12:21:36Z</published> - <updated>2017-05-10T12:21:36Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <summary xml:lang="sv">technologic</summary> - <content type="html" xml:lang="sv">&lt;p&gt;test&lt;/p&gt;</content> - <mastodon:scope>unlisted</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2314748"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2314748.atom"/> - </entry> -</feed> diff --git a/test/fixtures/mastodon-problematic.xml b/test/fixtures/mastodon-problematic.xml @@ -1,72 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://icosahedron.website/users/shel.atom</id> - <title>shel🍖‼️</title> - <subtitle>Gay jackal dog, poet, future librarian. - -http://datapup.info -avatar: @puppytube@twitter.com</subtitle> - <updated>2017-05-02T23:26:01Z</updated> - <logo>https://icosahedron.website/system/accounts/avatars/000/001/207/original/b1e07b09ae1cc787.png?1493767561</logo> - <author> - <id>https://icosahedron.website/users/shel</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://icosahedron.website/users/shel</uri> - <name>shel</name> - <email>shel@icosahedron.website</email> - <summary type="html">&lt;p&gt;Gay jackal dog, poet, future librarian. &lt;/p&gt;&lt;p&gt;&lt;a href="http://datapup.info/" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;http://&lt;/span&gt;&lt;span class=""&gt;datapup.info/&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;avatar: @puppytube@twitter.com&lt;/p&gt;</summary> - <link rel="alternate" type="text/html" href="https://icosahedron.website/@shel"/> - <link rel="avatar" type="image/png" media:width="120" media:height="120" href="https://icosahedron.website/system/accounts/avatars/000/001/207/original/b1e07b09ae1cc787.png?1493767561"/> - <link rel="header" type="image/jpeg" media:width="700" media:height="335" href="https://icosahedron.website/system/accounts/headers/000/001/207/original/13e50e0ddfe359fd.jpg?1493767561"/> - <poco:preferredUsername>shel</poco:preferredUsername> - <poco:displayName>shel🍖‼️</poco:displayName> - <poco:note>Gay jackal dog, poet, future librarian. - -http://datapup.info -avatar: @puppytube@twitter.com</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://icosahedron.website/@shel"/> - <link rel="self" type="application/atom+xml" href="https://icosahedron.website/users/shel.atom"/> - <link rel="hub" href="https://icosahedron.website/api/push"/> - <link rel="salmon" href="https://icosahedron.website/api/salmon/1207"/> - <entry> - <id>tag:icosahedron.website,2017-05-10:objectId=1414013:objectType=Status</id> - <published>2017-05-10T17:16:24Z</published> - <updated>2017-05-10T17:16:24Z</updated> - <title>shel shared a status by instance_names@cybre.space</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:cybre.space,2017-05-10:objectId=946671:objectType=Status</id> - <published>2017-05-10T17:15:51Z</published> - <updated>2017-05-10T17:15:52Z</updated> - <title>New status by instance_names@cybre.space</title> - <author> - <id>https://cybre.space/users/instance_names</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://cybre.space/users/instance_names</uri> - <name>instance_names</name> - <email>instance_names@cybre.space</email> - <summary type="html">&lt;p&gt;name ideas for your new mastodon instance. made by &lt;span class="h-card"&gt;&lt;a href="https://witches.town/@lycaon"&gt;@&lt;span&gt;lycaon&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; source available at &lt;a href="https://github.com/LycaonIsAWolf/instance_names"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class="ellipsis"&gt;github.com/LycaonIsAWolf/insta&lt;/span&gt;&lt;span class="invisible"&gt;nce_names&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</summary> - <link rel="alternate" type="text/html" href="https://cybre.space/@instance_names"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://icosahedron.website/system/accounts/avatars/000/011/176/original/3845c33e63aa28bd.jpg?1492882822"/> - <link rel="header" type="image/png" media:width="700" media:height="335" href="https://icosahedron.website/system/accounts/headers/000/011/176/original/a7810908beeeef7e.png?1492882825"/> - <poco:preferredUsername>instance_names</poco:preferredUsername> - <poco:displayName>instance names</poco:displayName> - <poco:note>name ideas for your new mastodon instance. made by @lycaon source available at https://github.com/LycaonIsAWolf/instance_names</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;dildo.codes&lt;/p&gt;</content> - <mastodon:scope>unlisted</mastodon:scope> - <link rel="alternate" type="text/html" href="https://cybre.space/users/instance_names/updates/37775"/> - </activity:object> - <content type="html" xml:lang="en">&lt;p&gt;dildo.codes&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://icosahedron.website/users/shel/updates/47932"/> - <link rel="self" type="application/atom+xml" href="https://icosahedron.website/users/shel/updates/47932.atom"/> - </entry> -</feed> diff --git a/test/fixtures/mastodon_conversation.xml b/test/fixtures/mastodon_conversation.xml @@ -1,30 +0,0 @@ -<?xml version="1.0"?> -<entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>tag:mastodon.social,2017-08-28:objectId=16402826:objectType=Status</id> - <published>2017-08-28T17:58:55Z</published> - <updated>2017-08-28T17:58:55Z</updated> - <title>New status by lambadalambda</title> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/> - <link rel="header" type="image/gif" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/000/264/original/28b26104f83747d2.gif"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/lambadalambda/statuses/16402826"/> - <content type="html" xml:lang="">&lt;p&gt;test. &lt;a href="https://mastodon.social/media/XCp0OHGPON9kWZwhjaI" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class="ellipsis"&gt;mastodon.social/media/XCp0OHGP&lt;/span&gt;&lt;span class="invisible"&gt;ON9kWZwhjaI&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" type="image/png" length="307682" href="https://files.mastodon.social/media_attachments/files/001/271/957/original/6b426b164a09a40e.png"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/4215320"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/4215320.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2017-08-28:objectId=7876885:objectType=Conversation"/> -</entry> diff --git a/test/fixtures/nil_mention_entry.xml b/test/fixtures/nil_mention_entry.xml @@ -1,52 +0,0 @@ -<?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/fixtures/ostatus_incoming_post.xml b/test/fixtures/ostatus_incoming_post.xml @@ -1,57 +0,0 @@ -<?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-04-29T18:25:38+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> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-04-29:noticeId=1967725:objectType=note</id> - <title>New note by lambadalambda</title> - <content type="html">Will it blend?</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1967725"/> - <status_net notice_id="1967725"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-29T18:25:38+00:00</published> - <updated>2017-04-29T18:25:38+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1007861"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1007861" local_id="1007861" ref="tag:social.heldscal.la,2017-04-29:objectType=thread:nonce=3f3a9dd83acc4e35">tag:social.heldscal.la,2017-04-29:objectType=thread:nonce=3f3a9dd83acc4e35</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/1967725.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1967725.atom"/> - <statusnet:notice_info local_id="1967725" source="Pleroma FE"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/ostatus_incoming_post_tag.xml b/test/fixtures/ostatus_incoming_post_tag.xml @@ -1,59 +0,0 @@ -<?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-04-29T18:25:38+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> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-04-29:noticeId=1967725:objectType=note</id> - <title>New note by lambadalambda</title> - <content type="html">Will it blend?</content> - <category term="Nsfw"/> - <category term=""/> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1967725"/> - <status_net notice_id="1967725"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-29T18:25:38+00:00</published> - <updated>2017-04-29T18:25:38+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1007861"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1007861" local_id="1007861" ref="tag:social.heldscal.la,2017-04-29:objectType=thread:nonce=3f3a9dd83acc4e35">tag:social.heldscal.la,2017-04-29:objectType=thread:nonce=3f3a9dd83acc4e35</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/1967725.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1967725.atom"/> - <statusnet:notice_info local_id="1967725" source="Pleroma FE"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/ostatus_incoming_reply.xml b/test/fixtures/ostatus_incoming_reply.xml @@ -1,60 +0,0 @@ -<?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-04-30T09:30:32+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> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-04-30:noticeId=1978790:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://gs.archae.me/user/4687&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;shpbot&quot;&gt;shpbot&lt;/a&gt; why not indeed.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1978790"/> - <status_net notice_id="1978790"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-30T09:30:32+00:00</published> - <updated>2017-04-30T09:30:32+00:00</updated> - <thr:in-reply-to ref="tag:gs.archae.me,2017-04-30:noticeId=778260:objectType=note" href="https://gs.archae.me/notice/778260"></thr:in-reply-to> - <link rel="related" href="https://gs.archae.me/notice/778260"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1013566"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1013566" local_id="1013566" ref="https://gs.archae.me/conversation/327120">https://gs.archae.me/conversation/327120</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.archae.me/user/4687"/> - <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/1978790.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1978790.atom"/> - <statusnet:notice_info local_id="1978790" source="Pleroma FE"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/share-gs-local.xml b/test/fixtures/share-gs-local.xml @@ -1,99 +0,0 @@ -<?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-03T08:05:41+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-03:noticeId=2028428:objectType=note</id> - <title>lambadalambda repeated a notice by lain</title> - <content type="html">RT @&lt;a href=&quot;https://pleroma.soykaf.com/users/lain&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Lain Iwakura&quot;&gt;lain&lt;/a&gt; Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2028428"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-05-03T08:05:41+00:00</published> - <updated>2017-05-03T08:05:41+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>LOCAL_ID</id> - <title></title> - <content type="html">Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-03T08:04:44+00:00</published> - <updated>2017-05-03T08:04:44+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>LOCAL_USER</uri> - <name>lain</name> - <summary>Test account</summary> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="avatar" type="image/jpeg" media:width="250" media:height="202" href="https://social.heldscal.la/avatar/43188-original-20170429171039.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/43188-96-20170429172422.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/43188-48-20170429172422.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/43188-24-20170429181411.jpeg"/> - <poco:preferredUsername>lain</poco:preferredUsername> - <poco:displayName>Lain Iwakura</poco:displayName> - <poco:note>Test account</poco:note> - <statusnet:profile_info local_id="43188"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193</id> - <title>New note by lain</title> - <content type="html">Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193"/> - <status_net notice_id="2028424"></status_net> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1042737"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1042737" local_id="1042737" ref="https://pleroma.soykaf.com/contexts/ede39a2b-7cf3-4fa4-8ccd-cb97431bcc22">https://pleroma.soykaf.com/contexts/ede39a2b-7cf3-4fa4-8ccd-cb97431bcc22</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>https://pleroma.soykaf.com/users/lain/feed.atom</id> - <title>Lain Iwakura</title> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/users/lain/feed.atom"/> - <icon>https://social.heldscal.la/avatar/43188-96-20170429172422.jpeg</icon> - <updated>2017-05-03T08:04:44+00:00</updated> - </source> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1042737"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1042737" local_id="1042737" ref="https://pleroma.soykaf.com/contexts/ede39a2b-7cf3-4fa4-8ccd-cb97431bcc22">https://pleroma.soykaf.com/contexts/ede39a2b-7cf3-4fa4-8ccd-cb97431bcc22</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/2028428.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2028428.atom"/> - <statusnet:notice_info local_id="2028428" source="api" repeat_of="2028424"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/share-gs.xml b/test/fixtures/share-gs.xml @@ -1,99 +0,0 @@ -<?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-03T08:05:41+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-03:noticeId=2028428:objectType=note</id> - <title>lambadalambda repeated a notice by lain</title> - <content type="html">RT @&lt;a href=&quot;https://pleroma.soykaf.com/users/lain&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Lain Iwakura&quot;&gt;lain&lt;/a&gt; Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2028428"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-05-03T08:05:41+00:00</published> - <updated>2017-05-03T08:05:41+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193</id> - <title></title> - <content type="html">Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-03T08:04:44+00:00</published> - <updated>2017-05-03T08:04:44+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://pleroma.soykaf.com/users/lain</uri> - <name>lain</name> - <summary>Test account</summary> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="avatar" type="image/jpeg" media:width="250" media:height="202" href="https://social.heldscal.la/avatar/43188-original-20170429171039.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/43188-96-20170429172422.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/43188-48-20170429172422.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/43188-24-20170429181411.jpeg"/> - <poco:preferredUsername>lain</poco:preferredUsername> - <poco:displayName>Lain Iwakura</poco:displayName> - <poco:note>Test account</poco:note> - <statusnet:profile_info local_id="43188"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193</id> - <title>New note by lain</title> - <content type="html">Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193"/> - <status_net notice_id="2028424"></status_net> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1042737"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1042737" local_id="1042737" ref="https://pleroma.soykaf.com/contexts/ede39a2b-7cf3-4fa4-8ccd-cb97431bcc22">https://pleroma.soykaf.com/contexts/ede39a2b-7cf3-4fa4-8ccd-cb97431bcc22</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>https://pleroma.soykaf.com/users/lain/feed.atom</id> - <title>Lain Iwakura</title> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/users/lain/feed.atom"/> - <icon>https://social.heldscal.la/avatar/43188-96-20170429172422.jpeg</icon> - <updated>2017-05-03T08:04:44+00:00</updated> - </source> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1042737"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1042737" local_id="1042737" ref="https://pleroma.soykaf.com/contexts/ede39a2b-7cf3-4fa4-8ccd-cb97431bcc22">https://pleroma.soykaf.com/contexts/ede39a2b-7cf3-4fa4-8ccd-cb97431bcc22</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/2028428.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2028428.atom"/> - <statusnet:notice_info local_id="2028428" source="api" repeat_of="2028424"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/share.xml b/test/fixtures/share.xml @@ -1,54 +0,0 @@ -<?xml version="1.0"?> -<entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>tag:mastodon.social,2017-05-03:objectId=4934452:objectType=Status</id> - <published>2017-05-03T08:21:09Z</published> - <updated>2017-05-03T08:21:09Z</updated> - <title>lambadalambda shared a status by lain@pleroma.soykaf.com</title> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193</id> - <published>2017-05-03T08:04:44Z</published> - <updated>2017-05-03T08:05:52Z</updated> - <title>New status by lain@pleroma.soykaf.com</title> - <author> - <id>https://pleroma.soykaf.com/users/lain</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://pleroma.soykaf.com/users/lain</uri> - <name>lain</name> - <email>lain@pleroma.soykaf.com</email> - <summary type="html">Test account</summary> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/125/902/original/6B3AFC74ACA841B24CFB94DB9044C84EDE6AFF31C71718B023D413DAED09A68E.jpeg"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lain</poco:preferredUsername> - <poco:displayName>Lain Iwakura</poco:displayName> - <poco:note>Test account</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href=""/> - </activity:object> - <content type="html" xml:lang="en">Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2232660"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2232660.atom"/> -</entry> diff --git a/test/fixtures/tesla_mock/7369654.atom b/test/fixtures/tesla_mock/7369654.atom @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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,2018-02-22:noticeId=7369654:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://testing.pleroma.lol/users/lain&quot; class=&quot;h-card mention&quot; title=&quot;Rael Electric Razor&quot;&gt;lain&lt;/a&gt; me far right</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7369654"/> - <status_net notice_id="7369654"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-22T09:20:12+00:00</published> - <updated>2018-02-22T09:20:12+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://shitposter.club/user/5381</uri> - <name>shpuld</name> - <link rel="alternate" type="text/html" href="https://shitposter.club/shpuld"/> - <link rel="avatar" type="image/png" media:width="864" media:height="864" href="https://shitposter.club/avatar/5381-original-20171230093854.png"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://shitposter.club/avatar/5381-96-20171230093854.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="https://shitposter.club/avatar/5381-48-20171230093854.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="https://shitposter.club/avatar/5381-24-20171230093900.png"/> - <poco:preferredUsername>shpuld</poco:preferredUsername> - <poco:displayName>shp</poco:displayName> - <followers url="https://shitposter.club/shpuld/subscribers"></followers> - <statusnet:profile_info local_id="5381"></statusnet:profile_info> - </author> - <thr:in-reply-to ref="https://testing.pleroma.lol/objects/b319022a-4946-44c5-9de9-34801f95507b" href="https://testing.pleroma.lol/objects/b319022a-4946-44c5-9de9-34801f95507b"></thr:in-reply-to> - <link rel="related" href="https://testing.pleroma.lol/objects/b319022a-4946-44c5-9de9-34801f95507b"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4378601"/> - <ostatus:conversation href="https://shitposter.club/conversation/4378601" local_id="4378601" ref="tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4">tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://testing.pleroma.lol/users/lain"/> - <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/5381.atom</id> - <title>shp</title> - <link rel="alternate" type="text/html" href="https://shitposter.club/shpuld"/> - <link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/user_timeline/5381.atom"/> - <link rel="license" href="https://shitposter.club/doc/tos"/> - <icon>https://shitposter.club/avatar/5381-96-20171230093854.png</icon> - <updated>2018-02-23T13:30:15+00:00</updated> - </source> - <link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7369654.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7369654.atom"/> - <statusnet:notice_info local_id="7369654" source="Pleroma FE"></statusnet:notice_info> -</entry> diff --git a/test/fixtures/tesla_mock/admin@mastdon.example.org.json b/test/fixtures/tesla_mock/admin@mastdon.example.org.json @@ -1,20 +1,24 @@ { - "@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", { - "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", - "sensitive": "as:sensitive", - "movedTo": "as:movedTo", - "Hashtag": "as:Hashtag", - "ostatus": "http://ostatus.org#", - "atomUri": "ostatus:atomUri", - "inReplyToAtomUri": "ostatus:inReplyToAtomUri", - "conversation": "ostatus:conversation", - "toot": "http://joinmastodon.org/ns#", - "Emoji": "toot:Emoji", - "alsoKnownAs": { - "@id": "as:alsoKnownAs", - "@type": "@id" + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "sensitive": "as:sensitive", + "movedTo": "as:movedTo", + "Hashtag": "as:Hashtag", + "ostatus": "http://ostatus.org#", + "atomUri": "ostatus:atomUri", + "inReplyToAtomUri": "ostatus:inReplyToAtomUri", + "conversation": "ostatus:conversation", + "toot": "http://joinmastodon.org/ns#", + "Emoji": "toot:Emoji", + "alsoKnownAs": { + "@id": "as:alsoKnownAs", + "@type": "@id" + } } - }], + ], "id": "http://mastodon.example.org/users/admin", "type": "Person", "following": "http://mastodon.example.org/users/admin/following", @@ -23,6 +27,7 @@ "outbox": "http://mastodon.example.org/users/admin/outbox", "preferredUsername": "admin", "name": null, + "discoverable": "true", "summary": "\u003cp\u003e\u003c/p\u003e", "url": "http://mastodon.example.org/@admin", "manuallyApprovesFollowers": false, @@ -34,7 +39,8 @@ "owner": "http://mastodon.example.org/users/admin", "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtc4Tir+3ADhSNF6VKrtW\nOU32T01w7V0yshmQei38YyiVwVvFu8XOP6ACchkdxbJ+C9mZud8qWaRJKVbFTMUG\nNX4+6Q+FobyuKrwN7CEwhDALZtaN2IPbaPd6uG1B7QhWorrY+yFa8f2TBM3BxnUy\nI4T+bMIZIEYG7KtljCBoQXuTQmGtuffO0UwJksidg2ffCF5Q+K//JfQagJ3UzrR+\nZXbKMJdAw4bCVJYs4Z5EhHYBwQWiXCyMGTd7BGlmMkY6Av7ZqHKC/owp3/0EWDNz\nNqF09Wcpr3y3e8nA10X40MJqp/wR+1xtxp+YGbq/Cj5hZGBG7etFOmIpVBrDOhry\nBwIDAQAB\n-----END PUBLIC KEY-----\n" }, - "attachment": [{ + "attachment": [ + { "type": "PropertyValue", "name": "foo", "value": "bar" @@ -58,5 +64,7 @@ "mediaType": "image/png", "url": "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png" }, - "alsoKnownAs": ["http://example.org/users/foo"] -} + "alsoKnownAs": [ + "http://example.org/users/foo" + ] +} +\ No newline at end of file diff --git a/test/fixtures/tesla_mock/atarifrosch_feed.xml b/test/fixtures/tesla_mock/atarifrosch_feed.xml @@ -1,473 +0,0 @@ -<?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/tesla_mock/emelie.atom b/test/fixtures/tesla_mock/emelie.atom @@ -1,306 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://mastodon.social/users/emelie.atom</id> - <title>emelie 🎨</title> - <subtitle>23 / #Sweden / #Artist / #Equestrian / #GameDev - -If I ain't spending time with my pets, I'm probably drawing. 🐴 🐱 🐰</subtitle> - <updated>2019-02-04T20:22:19Z</updated> - <logo>https://files.mastodon.social/accounts/avatars/000/015/657/original/e7163f98280da1a4.png</logo> - <author> - <id>https://mastodon.social/users/emelie</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/emelie</uri> - <name>emelie</name> - <email>emelie@mastodon.social</email> - <summary type="html">&lt;p&gt;23 / &lt;a href="https://mastodon.social/tags/sweden" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;Sweden&lt;/span&gt;&lt;/a&gt; / &lt;a href="https://mastodon.social/tags/artist" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;Artist&lt;/span&gt;&lt;/a&gt; / &lt;a href="https://mastodon.social/tags/equestrian" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;Equestrian&lt;/span&gt;&lt;/a&gt; / &lt;a href="https://mastodon.social/tags/gamedev" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;GameDev&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If I ain&amp;apos;t spending time with my pets, I&amp;apos;m probably drawing. 🐴 🐱 🐰&lt;/p&gt;</summary> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie"/> - <link rel="avatar" type="image/png" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/015/657/original/e7163f98280da1a4.png"/> - <link rel="header" type="image/png" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/015/657/original/847f331f3dd9e38b.png"/> - <poco:preferredUsername>emelie</poco:preferredUsername> - <poco:displayName>emelie 🎨</poco:displayName> - <poco:note>23 / #Sweden / #Artist / #Equestrian / #GameDev - -If I ain't spending time with my pets, I'm probably drawing. 🐴 🐱 🐰</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie.atom"/> - <link rel="hub" href="https://mastodon.social/api/push"/> - <link rel="salmon" href="https://mastodon.social/api/salmon/15657"/> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101850331907006641</id> - <published>2019-04-01T09:58:50Z</published> - <updated>2019-04-01T09:58:50Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101850331907006641"/> - <content type="html" xml:lang="en">&lt;p&gt;Me: I&amp;apos;m going to make this vital change to my world building in the morning, no way I&amp;apos;ll forget this, it&amp;apos;s too big of a deal&lt;br /&gt;Also me: forgets&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101850331907006641"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17854598.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94383214:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101849626603073336</id> - <published>2019-04-01T06:59:28Z</published> - <updated>2019-04-01T06:59:28Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849626603073336"/> - <content type="html" xml:lang="sv">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@Fergant" class="u-url mention"&gt;@&lt;span&gt;Fergant&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Dom är i stort sett religiös skrift vid det här laget 👏👏&lt;/p&gt;&lt;p&gt;har dock bara läst svenska översättningen, kanske är dags att jag läser dom på engelska&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/Fergant"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849626603073336"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17852590.atom"/> - <thr:in-reply-to ref="https://mastodon.social/users/Fergant/statuses/101849606513357387" href="https://mastodon.social/@Fergant/101849606513357387"/> - <ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94362529:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101849580030237068</id> - <published>2019-04-01T06:47:37Z</published> - <updated>2019-04-01T06:47:37Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849580030237068"/> - <content type="html" xml:lang="en">&lt;p&gt;What&amp;apos;s you people&amp;apos;s favourite fantasy books? Give me some hot tips 🌞&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849580030237068"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17852464.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94362529:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101849550599949363</id> - <published>2019-04-01T06:40:08Z</published> - <updated>2019-04-01T06:40:08Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849550599949363"/> - <content type="html" xml:lang="en">&lt;p&gt;Stick them legs out 💃 &lt;a href="https://mastodon.social/tags/mastocats" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;mastocats&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="mastocats"/> - <link rel="enclosure" type="image/jpeg" length="516384" href="https://files.mastodon.social/media_attachments/files/013/051/707/original/125a310abe9a34aa.jpeg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849550599949363"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17852407.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94361580:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101849191533152720</id> - <published>2019-04-01T05:08:49Z</published> - <updated>2019-04-01T05:08:49Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849191533152720"/> - <content type="html" xml:lang="en">&lt;p&gt;long 🐱 &lt;a href="https://mastodon.social/tags/mastocats" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;mastocats&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="mastocats"/> - <link rel="enclosure" type="image/jpeg" length="305208" href="https://files.mastodon.social/media_attachments/files/013/049/940/original/f2dbbfe7de3a17d2.jpeg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849191533152720"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17851663.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94351141:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101849165031453009</id> - <published>2019-04-01T05:02:05Z</published> - <updated>2019-04-01T05:02:05Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101849165031453009"/> - <content type="html" xml:lang="en">&lt;p&gt;You gotta take whatever bellyrubbing opportunity you can get before she changes her mind 🦁 &lt;a href="https://mastodon.social/tags/mastocats" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;mastocats&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="mastocats"/> - <link rel="enclosure" type="video/mp4" length="9838915" href="https://files.mastodon.social/media_attachments/files/013/049/816/original/e7831178a5e0d6d4.mp4"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101849165031453009"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17851558.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-04-01:objectId=94350309:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101846512530748693</id> - <published>2019-03-31T17:47:31Z</published> - <updated>2019-03-31T17:47:31Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101846512530748693"/> - <content type="html" xml:lang="en">&lt;p&gt;Hello look at this boy having a decent haircut for once &lt;a href="https://mastodon.social/tags/mastohorses" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;mastohorses&lt;/span&gt;&lt;/a&gt; &lt;a href="https://mastodon.social/tags/equestrian" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;equestrian&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="equestrian"/> - <category term="mastohorses"/> - <link rel="enclosure" type="image/jpeg" length="461632" href="https://files.mastodon.social/media_attachments/files/013/033/387/original/301e8ab668cd61d2.jpeg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101846512530748693"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17842424.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-31:objectId=94256415:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101846181093805500</id> - <published>2019-03-31T16:23:14Z</published> - <updated>2019-03-31T16:23:14Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101846181093805500"/> - <content type="html" xml:lang="en">&lt;p&gt;Sorry did I disturb the who-is-the-longest-cat competition ? &lt;a href="https://mastodon.social/tags/mastocats" class="mention hashtag" rel="tag"&gt;#&lt;span&gt;mastocats&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="mastocats"/> - <link rel="enclosure" type="image/jpeg" length="211384" href="https://files.mastodon.social/media_attachments/files/013/030/725/original/5b4886730cbbd25c.jpeg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101846181093805500"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17841108.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-31:objectId=94245239:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101845897513133849</id> - <published>2019-03-31T15:11:07Z</published> - <updated>2019-03-31T15:11:07Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101845897513133849"/> - <summary xml:lang="en">more earthsea ramblings</summary> - <content type="html" xml:lang="en">&lt;p&gt;I&amp;apos;m re-watching Tales from Earthsea for the first time since I read the books, and that Therru doesn&amp;apos;t squash Cob like a spider, as Orm Embar did is a wasted opportunity tbh&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101845897513133849"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17840088.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-31:objectId=94232455:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101841219051533307</id> - <published>2019-03-30T19:21:19Z</published> - <updated>2019-03-30T19:21:19Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101841219051533307"/> - <content type="html" xml:lang="en">&lt;p&gt;I gave my cats some mackerel and they ate it all in 0.3 seconds, and now they won&amp;apos;t stop meowing for more, and I&amp;apos;m tired plz shut up&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101841219051533307"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17826587.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-30:objectId=94075000:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101839949762341381</id> - <published>2019-03-30T13:58:31Z</published> - <updated>2019-03-30T13:58:31Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101839949762341381"/> - <content type="html" xml:lang="en">&lt;p&gt;yet I&amp;apos;m confused about this american dude with a gun, like the heck r ya doin in mah ghibli&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101839949762341381"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17821757.atom"/> - <thr:in-reply-to ref="https://mastodon.social/users/emelie/statuses/101839928677863590" href="https://mastodon.social/@emelie/101839928677863590"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-30:objectId=94026360:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101839928677863590</id> - <published>2019-03-30T13:53:09Z</published> - <updated>2019-03-30T13:53:09Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101839928677863590"/> - <content type="html" xml:lang="en">&lt;p&gt;2 hours into Ni no Kuni 2 and I&amp;apos;ve already sold my soul to this game&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101839928677863590"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17821713.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-30:objectId=94026360:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101836329521599438</id> - <published>2019-03-29T22:37:51Z</published> - <updated>2019-03-29T22:37:51Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101836329521599438"/> - <content type="html" xml:lang="en">&lt;p&gt;Pippi Longstocking the original one-punch /man&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101836329521599438"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17811608.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-29:objectId=93907854:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101835905282948341</id> - <published>2019-03-29T20:49:57Z</published> - <updated>2019-03-29T20:49:57Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101835905282948341"/> - <content type="html" xml:lang="en">&lt;p&gt;I&amp;apos;ve had so much wine I thought I had a 3rd brother&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101835905282948341"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17809862.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-29:objectId=93892966:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101835878059204660</id> - <published>2019-03-29T20:43:02Z</published> - <updated>2019-03-29T20:43:02Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101835878059204660"/> - <content type="html" xml:lang="en">&lt;p&gt;ååååhhh booi&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101835878059204660"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17809734.atom"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-29:objectId=93892010:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101835848050598939</id> - <published>2019-03-29T20:35:24Z</published> - <updated>2019-03-29T20:35:24Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101835848050598939"/> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://thraeryn.net/@thraeryn" class="u-url mention"&gt;@&lt;span&gt;thraeryn&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; if I spent 1 hour and a half watching this monstrosity, I need to&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://thraeryn.net/users/thraeryn"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101835848050598939"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17809591.atom"/> - <thr:in-reply-to ref="https://thraeryn.net/users/thraeryn/statuses/101835839202826007" href="https://thraeryn.net/@thraeryn/101835839202826007"/> - <ostatus:conversation ref="tag:mastodon.social,2019-03-29:objectId=93888827:objectType=Conversation"/> - </entry> - <entry> - <id>https://mastodon.social/users/emelie/statuses/101835823138262290</id> - <published>2019-03-29T20:29:04Z</published> - <updated>2019-03-29T20:29:04Z</updated> - <title>New status by emelie</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <link rel="alternate" type="application/activity+json" href="https://mastodon.social/users/emelie/statuses/101835823138262290"/> - <summary xml:lang="en">medical, fluids mention</summary> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://icosahedron.website/@Trev" class="u-url mention"&gt;@&lt;span&gt;Trev&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; *hugs* ✨&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://icosahedron.website/users/Trev"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/@emelie/101835823138262290"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/emelie/updates/17809468.atom"/> - <thr:in-reply-to ref="https://icosahedron.website/users/Trev/statuses/101835812250051801" href="https://icosahedron.website/@Trev/101835812250051801"/> - <ostatus:conversation ref="tag:icosahedron.website,2019-03-29:objectId=12220882:objectType=Conversation"/> - </entry> -</feed> diff --git a/test/fixtures/tesla_mock/framatube.org-video.json b/test/fixtures/tesla_mock/framatube.org-video.json @@ -1 +1 @@ -{"type":"Video","id":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206","name":"Déframasoftisons Internet [Framasoft]","duration":"PT3622S","uuid":"6050732a-8a7a-43d4-a6cd-809525a1d206","tag":[{"type":"Hashtag","name":"déframasoftisons"},{"type":"Hashtag","name":"EPN23"},{"type":"Hashtag","name":"framaconf"},{"type":"Hashtag","name":"Framasoft"},{"type":"Hashtag","name":"pyg"}],"category":{"identifier":"15","name":"Science & Technology"},"views":122,"sensitive":false,"waitTranscoding":false,"state":1,"commentsEnabled":true,"downloadEnabled":true,"published":"2020-05-24T18:34:31.569Z","originallyPublishedAt":"2019-11-30T23:00:00.000Z","updated":"2020-07-05T09:01:01.720Z","mediaType":"text/markdown","content":"Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?\r\n\r\nTranscription par @april...","support":null,"subtitleLanguage":[],"icon":{"type":"Image","url":"https://framatube.org/static/thumbnails/6050732a-8a7a-43d4-a6cd-809525a1d206.jpg","mediaType":"image/jpeg","width":223,"height":122},"url":[{"type":"Link","mediaType":"text/html","href":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080,"size":1157359410,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309939","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent&xt=urn:btih:381c9429900552e23a4eb506318f1fa01e4d63a8&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480,"size":250095131,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309941","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent&xt=urn:btih:a181dcbb5368ab5c31cc9ff07634becb72c344ee&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360,"size":171357733,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309942","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent&xt=urn:btih:aedfa9479ea04a175eee0b0bd0bda64076308746&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720,"size":497100839,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309943","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent&xt=urn:btih:71971668f82a3b24ac71bc3a982848dd8dc5a5f5&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240,"size":113038439,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309944","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent&xt=urn:btih:c42aa6c95efb28d9f114ebd98537f7b00fa72246&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240},{"type":"Link","mediaType":"application/x-mpegURL","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/master.m3u8","tag":[{"type":"Infohash","name":"f7428214539626e062f300f2ca4cf9154575144e"},{"type":"Infohash","name":"46e236dffb1ea6b9123a5396cbe88e97dd94cc6c"},{"type":"Infohash","name":"11f1045830b5d786c788f2594d19f128764e7d87"},{"type":"Infohash","name":"4327ad3e0d84de100130a27e9ab6fe40c4284f0e"},{"type":"Infohash","name":"41e2eee8e7b23a63c23a77c40a46de11492a4831"},{"type":"Link","name":"sha256","mediaType":"application/json","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/segments-sha256.json"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080,"size":1156777472,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309940","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent&xt=urn:btih:0204d780ebfab0d5d9d3476a038e812ad792deeb&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480,"size":249562889,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309945","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent&xt=urn:btih:5d14f38ded29de629668fe1cfc61a75f4cce2628&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360,"size":170836415,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309946","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent&xt=urn:btih:30125488789080ad405ebcee6c214945f31b8f30&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720,"size":496533741,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309947","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent&xt=urn:btih:8ed1e8bccde709901c26e315fc8f53bfd26d1ba6&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240,"size":112529249,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309948","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent&xt=urn:btih:8b452bf4e70b9078d4e74ca8b5523cc9dc70d10a&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240}]}],"likes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/likes","dislikes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/dislikes","shares":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/announces","comments":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/comments","attributedTo":[{"type":"Person","id":"https://framatube.org/accounts/framasoft"},{"type":"Group","id":"https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8"}],"to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://framatube.org/accounts/framasoft/followers"],"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"RsaSignature2017":"https://w3id.org/security#RsaSignature2017"},{"pt":"https://joinpeertube.org/ns#","sc":"http://schema.org#","Hashtag":"as:Hashtag","uuid":"sc:identifier","category":"sc:category","licence":"sc:license","subtitleLanguage":"sc:subtitleLanguage","sensitive":"as:sensitive","language":"sc:inLanguage","Infohash":"pt:Infohash","Playlist":"pt:Playlist","PlaylistElement":"pt:PlaylistElement","originallyPublishedAt":"sc:datePublished","views":{"@type":"sc:Number","@id":"pt:views"},"state":{"@type":"sc:Number","@id":"pt:state"},"size":{"@type":"sc:Number","@id":"pt:size"},"fps":{"@type":"sc:Number","@id":"pt:fps"},"startTimestamp":{"@type":"sc:Number","@id":"pt:startTimestamp"},"stopTimestamp":{"@type":"sc:Number","@id":"pt:stopTimestamp"},"position":{"@type":"sc:Number","@id":"pt:position"},"commentsEnabled":{"@type":"sc:Boolean","@id":"pt:commentsEnabled"},"downloadEnabled":{"@type":"sc:Boolean","@id":"pt:downloadEnabled"},"waitTranscoding":{"@type":"sc:Boolean","@id":"pt:waitTranscoding"},"support":{"@type":"sc:Text","@id":"pt:support"},"likes":{"@id":"as:likes","@type":"@id"},"dislikes":{"@id":"as:dislikes","@type":"@id"},"playlists":{"@id":"pt:playlists","@type":"@id"},"shares":{"@id":"as:shares","@type":"@id"},"comments":{"@id":"as:comments","@type":"@id"}}]} -\ No newline at end of file +{"type":"Create","id":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/activity","actor":"https://framatube.org/accounts/framasoft","object":{"type":"Video","id":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206","name":"Déframasoftisons Internet [Framasoft]","duration":"PT3622S","uuid":"6050732a-8a7a-43d4-a6cd-809525a1d206","tag":[{"type":"Hashtag","name":"déframasoftisons"},{"type":"Hashtag","name":"EPN23"},{"type":"Hashtag","name":"framaconf"},{"type":"Hashtag","name":"Framasoft"},{"type":"Hashtag","name":"pyg"}],"category":{"identifier":"15","name":"Science & Technology"},"views":154,"sensitive":false,"waitTranscoding":false,"state":1,"commentsEnabled":true,"downloadEnabled":true,"published":"2020-05-24T18:34:31.569Z","originallyPublishedAt":"2019-11-30T23:00:00.000Z","updated":"2020-08-17T11:01:02.994Z","mediaType":"text/markdown","content":"Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?\r\n\r\nTranscription par @aprilorg ici : https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft","support":null,"subtitleLanguage":[],"icon":[{"type":"Image","url":"https://framatube.org/static/thumbnails/6050732a-8a7a-43d4-a6cd-809525a1d206.jpg","mediaType":"image/jpeg","width":223,"height":122},{"type":"Image","url":"https://framatube.org/static/previews/6050732a-8a7a-43d4-a6cd-809525a1d206.jpg","mediaType":"image/jpeg","width":850,"height":480}],"url":[{"type":"Link","mediaType":"text/html","href":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080,"size":1157359410,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309939","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.torrent&xt=urn:btih:381c9429900552e23a4eb506318f1fa01e4d63a8&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720,"size":497100839,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309943","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.torrent&xt=urn:btih:71971668f82a3b24ac71bc3a982848dd8dc5a5f5&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480,"size":250095131,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309941","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.torrent&xt=urn:btih:a181dcbb5368ab5c31cc9ff07634becb72c344ee&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360,"size":171357733,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309942","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.torrent&xt=urn:btih:aedfa9479ea04a175eee0b0bd0bda64076308746&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240,"size":113038439,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309944","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.torrent&xt=urn:btih:c42aa6c95efb28d9f114ebd98537f7b00fa72246&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240.mp4","height":240},{"type":"Link","mediaType":"application/x-mpegURL","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/master.m3u8","tag":[{"type":"Infohash","name":"f7428214539626e062f300f2ca4cf9154575144e"},{"type":"Infohash","name":"46e236dffb1ea6b9123a5396cbe88e97dd94cc6c"},{"type":"Infohash","name":"11f1045830b5d786c788f2594d19f128764e7d87"},{"type":"Infohash","name":"4327ad3e0d84de100130a27e9ab6fe40c4284f0e"},{"type":"Infohash","name":"41e2eee8e7b23a63c23a77c40a46de11492a4831"},{"type":"Link","name":"sha256","mediaType":"application/json","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/segments-sha256.json"},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080,"size":1156777472,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309940","height":1080,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent","height":1080},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-hls.torrent&xt=urn:btih:0204d780ebfab0d5d9d3476a038e812ad792deeb&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-1080-fragmented.mp4","height":1080},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720,"size":496533741,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309947","height":720,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent","height":720},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-hls.torrent&xt=urn:btih:8ed1e8bccde709901c26e315fc8f53bfd26d1ba6&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-720-fragmented.mp4","height":720},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480,"size":249562889,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309945","height":480,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent","height":480},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-hls.torrent&xt=urn:btih:5d14f38ded29de629668fe1cfc61a75f4cce2628&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-480-fragmented.mp4","height":480},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360,"size":170836415,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309946","height":360,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent","height":360},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-hls.torrent&xt=urn:btih:30125488789080ad405ebcee6c214945f31b8f30&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-360-fragmented.mp4","height":360},{"type":"Link","mediaType":"video/mp4","href":"https://framatube.org/static/streaming-playlists/hls/6050732a-8a7a-43d4-a6cd-809525a1d206/6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240,"size":112529249,"fps":25},{"type":"Link","rel":["metadata","video/mp4"],"mediaType":"application/json","href":"https://framatube.org/api/v1/videos/6050732a-8a7a-43d4-a6cd-809525a1d206/metadata/1309948","height":240,"fps":25},{"type":"Link","mediaType":"application/x-bittorrent","href":"https://framatube.org/static/torrents/6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent","height":240},{"type":"Link","mediaType":"application/x-bittorrent;x-scheme-handler/magnet","href":"magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-hls.torrent&xt=urn:btih:8b452bf4e70b9078d4e74ca8b5523cc9dc70d10a&dn=D%C3%A9framasoftisons+Internet+%5BFramasoft%5D&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F6050732a-8a7a-43d4-a6cd-809525a1d206%2F6050732a-8a7a-43d4-a6cd-809525a1d206-240-fragmented.mp4","height":240}]}],"likes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/likes","dislikes":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/dislikes","shares":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/announces","comments":"https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206/comments","attributedTo":[{"type":"Person","id":"https://framatube.org/accounts/framasoft"},{"type":"Group","id":"https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8"}],"to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://framatube.org/accounts/framasoft/followers"]},"to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://framatube.org/accounts/framasoft/followers"],"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"RsaSignature2017":"https://w3id.org/security#RsaSignature2017"},{"pt":"https://joinpeertube.org/ns#","sc":"http://schema.org#","Hashtag":"as:Hashtag","uuid":"sc:identifier","category":"sc:category","licence":"sc:license","subtitleLanguage":"sc:subtitleLanguage","sensitive":"as:sensitive","language":"sc:inLanguage","Infohash":"pt:Infohash","Playlist":"pt:Playlist","PlaylistElement":"pt:PlaylistElement","originallyPublishedAt":"sc:datePublished","views":{"@type":"sc:Number","@id":"pt:views"},"state":{"@type":"sc:Number","@id":"pt:state"},"size":{"@type":"sc:Number","@id":"pt:size"},"fps":{"@type":"sc:Number","@id":"pt:fps"},"startTimestamp":{"@type":"sc:Number","@id":"pt:startTimestamp"},"stopTimestamp":{"@type":"sc:Number","@id":"pt:stopTimestamp"},"position":{"@type":"sc:Number","@id":"pt:position"},"commentsEnabled":{"@type":"sc:Boolean","@id":"pt:commentsEnabled"},"downloadEnabled":{"@type":"sc:Boolean","@id":"pt:downloadEnabled"},"waitTranscoding":{"@type":"sc:Boolean","@id":"pt:waitTranscoding"},"support":{"@type":"sc:Text","@id":"pt:support"},"likes":{"@id":"as:likes","@type":"@id"},"dislikes":{"@id":"as:dislikes","@type":"@id"},"playlists":{"@id":"pt:playlists","@type":"@id"},"shares":{"@id":"as:shares","@type":"@id"},"comments":{"@id":"as:comments","@type":"@id"}}]} +\ No newline at end of file diff --git a/test/fixtures/tesla_mock/http__gs.example.org_index.php_api_statuses_user_timeline_1.atom.xml b/test/fixtures/tesla_mock/http__gs.example.org_index.php_api_statuses_user_timeline_1.atom.xml @@ -1,460 +0,0 @@ -<?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-beta4">GNU social</generator> - <id>http://gs.example.org/index.php/api/statuses/user_timeline/1.atom</id> - <title>lambda timeline</title> - <subtitle>Updates from lambda on gs.example.org!</subtitle> - <logo>http://gs.example.org/theme/neo-gnu/default-avatar-profile.png</logo> - <updated>2017-05-05T12:09:57+00:00</updated> -<author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>http://gs.example.org:4040/index.php/user/1</uri> - <name>lambda</name> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/lambda"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://gs.example.org/theme/neo-gnu/default-avatar-profile.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://gs.example.org/theme/neo-gnu/default-avatar-stream.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://gs.example.org/theme/neo-gnu/default-avatar-mini.png"/> - <poco:preferredUsername>lambda</poco:preferredUsername> - <poco:displayName>lambda</poco:displayName> - <followers url="http://gs.example.org/index.php/lambda/subscribers"></followers> - <statusnet:profile_info local_id="1"></statusnet:profile_info> -</author> - <link href="http://gs.example.org/index.php/lambda" rel="alternate" type="text/html"/> - <link href="http://gs.example.org/index.php/main/sup" rel="http://api.friendfeed.com/2008/03#sup" type="application/json"/> - <link href="http://gs.example.org/index.php/api/statuses/user_timeline/1.atom?max_id=34" rel="next" type="application/atom+xml"/> - <link href="http://gs.example.org/index.php/main/push/hub" rel="hub"/> - <link href="http://gs.example.org/index.php/main/salmon/user/1" rel="salmon"/> - <link href="http://gs.example.org/index.php/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-replies"/> - <link href="http://gs.example.org/index.php/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-mention"/> - <link href="http://gs.example.org/index.php/api/statuses/user_timeline/1.atom" rel="self" type="application/atom+xml"/> -<entry> - <id>tag:gs.example.org,2017-05-04:noticeId=84:objectType=note</id> - <title>lambda repeated a notice by lambda2</title> - <content type="html">RT @&lt;a href=&quot;http://gs.example.org/index.php/user/7&quot; class=&quot;h-card mention&quot;&gt;lambda2&lt;/a&gt; Hello!</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/84"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-05-04T16:38:50+00:00</published> - <updated>2017-05-04T16:38:50+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>tag:gs.example.org,2017-05-01:noticeId=67:objectType=note</id> - <title></title> - <content type="html">Hello!</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/67"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-01T08:41:04+00:00</published> - <updated>2017-05-01T08:41:04+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>http://gs.example.org/index.php/user/7</uri> - <name>lambda2</name> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/lambda2"/> - <link rel="avatar" type="image/png" media:width="270" media:height="270" href="http://gs.example.org/avatar/7-270-20170501084053.png"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://gs.example.org/avatar/7-96-20170501084054.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://gs.example.org/avatar/7-48-20170501084104.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://gs.example.org/avatar/7-24-20170501084104.png"/> - <poco:preferredUsername>lambda2</poco:preferredUsername> - <poco:displayName>lambda2</poco:displayName> - <followers url="http://gs.example.org/index.php/lambda2/subscribers"></followers> - <statusnet:profile_info local_id="7"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org,2017-05-01:noticeId=67:objectType=note</id> - <title>New note by lambda2</title> - <content type="html">Hello!</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/67"/> - <status_net notice_id="67"></status_net> - </activity:object> - <link rel="ostatus:conversation" href="tag:gs.example.org,2017-05-01:objectType=thread:nonce=cffa792cb95fe417"/> - <ostatus:conversation>tag:gs.example.org,2017-05-01:objectType=thread:nonce=cffa792cb95fe417</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>http://gs.example.org/index.php/api/statuses/user_timeline/7.atom</id> - <title>lambda2</title> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/lambda2"/> - <link rel="self" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/user_timeline/7.atom"/> - <link rel="license" href="https://creativecommons.org/licenses/by/3.0/"/> - <icon>http://gs.example.org/avatar/7-96-20170501084054.png</icon> - <updated>2017-05-01T16:33:10+00:00</updated> - </source> - <link rel="self" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/67.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/67.atom"/> - </activity:object> - <link rel="ostatus:conversation" href="tag:gs.example.org,2017-05-01:objectType=thread:nonce=cffa792cb95fe417"/> - <ostatus:conversation>tag:gs.example.org,2017-05-01:objectType=thread:nonce=cffa792cb95fe417</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="http://gs.example.org/index.php/api/statuses/show/84.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/84.atom"/> - <statusnet:notice_info local_id="84" source="web" repeat_of="67"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org,2017-04-30:noticeId=63:objectType=note</id> - <title>New note by lambda</title> - <content type="html">what now?</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/63"/> - <status_net notice_id="63"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-30T10:09:57+00:00</published> - <updated>2017-04-30T10:09:57+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/477d8933-7591-4755-ba7a-2c34073ddc3c" href="http://pleroma.example.org:4000/objects/477d8933-7591-4755-ba7a-2c34073ddc3c"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/477d8933-7591-4755-ba7a-2c34073ddc3c"/> - <link rel="ostatus:conversation" href="tag:gs.example.org,2017-04-30:objectType=thread:nonce=1bbb60991ae9874b"/> - <ostatus:conversation>tag:gs.example.org,2017-04-30:objectType=thread:nonce=1bbb60991ae9874b</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/63.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/63.atom"/> - <statusnet:notice_info local_id="63" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org,2017-04-30:noticeId=61:objectType=note</id> - <title>New note by lambda</title> - <content type="html">@&lt;a href=&quot;http://pleroma.example.org:4000/users/lain5&quot; class=&quot;h-card mention&quot;&gt;lain5&lt;/a&gt; Hello!</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/61"/> - <status_net notice_id="61"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-30T10:07:26+00:00</published> - <updated>2017-04-30T10:07:26+00:00</updated> - <link rel="ostatus:conversation" href="tag:gs.example.org,2017-04-30:objectType=thread:nonce=1bbb60991ae9874b"/> - <ostatus:conversation>tag:gs.example.org,2017-04-30:objectType=thread:nonce=1bbb60991ae9874b</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/61.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/61.atom"/> - <statusnet:notice_info local_id="61" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org,2017-04-29:noticeId=59:objectType=note</id> - <title>New note by lambda</title> - <content type="html">ey</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/59"/> - <status_net notice_id="59"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-29T17:04:59+00:00</published> - <updated>2017-04-29T17:04:59+00:00</updated> - <link rel="ostatus:conversation" href="tag:gs.example.org,2017-04-29:objectType=thread:nonce=4cc42c2c61a0f4bd"/> - <ostatus:conversation>tag:gs.example.org,2017-04-29:objectType=thread:nonce=4cc42c2c61a0f4bd</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="http://gs.example.org/index.php/api/statuses/show/59.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/59.atom"/> - <statusnet:notice_info local_id="59" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org,2017-04-29:noticeId=58:objectType=note</id> - <title>New note by lambda</title> - <content type="html">Another one.</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/58"/> - <status_net notice_id="58"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-29T17:02:47+00:00</published> - <updated>2017-04-29T17:02:47+00:00</updated> - <link rel="ostatus:conversation" href="tag:gs.example.org,2017-04-29:objectType=thread:nonce=53e9b8f1d6d38d13"/> - <ostatus:conversation>tag:gs.example.org,2017-04-29:objectType=thread:nonce=53e9b8f1d6d38d13</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="http://gs.example.org/index.php/api/statuses/show/58.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/58.atom"/> - <statusnet:notice_info local_id="58" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org,2017-04-29:noticeId=57:objectType=note</id> - <title>New note by lambda</title> - <content type="html">Let's see if this comes over.</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/57"/> - <status_net notice_id="57"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-29T17:01:39+00:00</published> - <updated>2017-04-29T17:01:39+00:00</updated> - <link rel="ostatus:conversation" href="tag:gs.example.org,2017-04-29:objectType=thread:nonce=238a7bd3ffc7c9cc"/> - <ostatus:conversation>tag:gs.example.org,2017-04-29:objectType=thread:nonce=238a7bd3ffc7c9cc</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="http://gs.example.org/index.php/api/statuses/show/57.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/57.atom"/> - <statusnet:notice_info local_id="57" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org,2017-04-29:noticeId=56:objectType=note</id> - <title>New note by lambda</title> - <content type="html">@&lt;a href=&quot;http://pleroma.example.org:4000/users/lain5&quot; class=&quot;h-card mention&quot;&gt;lain5&lt;/a&gt; Hey!</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/56"/> - <status_net notice_id="56"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-29T16:38:13+00:00</published> - <updated>2017-04-29T16:38:13+00:00</updated> - <link rel="ostatus:conversation" href="tag:gs.example.org,2017-04-29:objectType=thread:nonce=2629d3a398171b0f"/> - <ostatus:conversation>tag:gs.example.org,2017-04-29:objectType=thread:nonce=2629d3a398171b0f</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/56.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/56.atom"/> - <statusnet:notice_info local_id="56" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=55:objectType=note</id> - <title>New note by lambda</title> - <content type="html">hey.</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/55"/> - <status_net notice_id="55"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T18:16:13+00:00</published> - <updated>2017-04-25T18:16:13+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/55bce8fc-b423-46b1-af71-3759ab4670bc" href="http://pleroma.example.org:4000/objects/55bce8fc-b423-46b1-af71-3759ab4670bc"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/55bce8fc-b423-46b1-af71-3759ab4670bc"/> - <link rel="ostatus:conversation" href="http://pleroma.example.org:4000/contexts/8f6f45d4-8e4d-4e1a-a2de-09f27367d2d0"/> - <ostatus:conversation>http://pleroma.example.org:4000/contexts/8f6f45d4-8e4d-4e1a-a2de-09f27367d2d0</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/55.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/55.atom"/> - <statusnet:notice_info local_id="55" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=53:objectType=note</id> - <title>New note by lambda</title> - <content type="html">and this?</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/53"/> - <status_net notice_id="53"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T18:14:34+00:00</published> - <updated>2017-04-25T18:14:34+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/875b219f-8ced-4948-832e-137a06a88031" href="http://pleroma.example.org:4000/objects/875b219f-8ced-4948-832e-137a06a88031"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/875b219f-8ced-4948-832e-137a06a88031"/> - <link rel="ostatus:conversation" href="http://pleroma.example.org:4000/contexts/24779b0e-91ad-487e-81bd-6cf5bb437b09"/> - <ostatus:conversation>http://pleroma.example.org:4000/contexts/24779b0e-91ad-487e-81bd-6cf5bb437b09</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/53.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/53.atom"/> - <statusnet:notice_info local_id="53" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=52:objectType=note</id> - <title>New note by lambda</title> - <content type="html">yeah it does :)</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/52"/> - <status_net notice_id="52"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T18:13:31+00:00</published> - <updated>2017-04-25T18:13:31+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/9c0430b4-ccb3-4e2c-9c50-ee345ebe18fc" href="http://pleroma.example.org:4000/objects/9c0430b4-ccb3-4e2c-9c50-ee345ebe18fc"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/9c0430b4-ccb3-4e2c-9c50-ee345ebe18fc"/> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=e0dc24b1a93ab6b3"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=e0dc24b1a93ab6b3</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/52.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/52.atom"/> - <statusnet:notice_info local_id="52" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=50:objectType=note</id> - <title>New note by lambda</title> - <content type="html">@&lt;a href=&quot;http://pleroma.example.org:4000/users/lain5&quot; class=&quot;h-card mention&quot;&gt;lain5&lt;/a&gt; Let's try with one that originates here!</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/50"/> - <status_net notice_id="50"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T18:10:28+00:00</published> - <updated>2017-04-25T18:10:28+00:00</updated> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=e0dc24b1a93ab6b3"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=e0dc24b1a93ab6b3</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/50.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/50.atom"/> - <statusnet:notice_info local_id="50" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=48:objectType=note</id> - <title>New note by lambda</title> - <content type="html">works?</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/48"/> - <status_net notice_id="48"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T18:08:44+00:00</published> - <updated>2017-04-25T18:08:44+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/8664caae-1cd6-4c1f-b1d7-27bd4ce76966" href="http://pleroma.example.org:4000/objects/8664caae-1cd6-4c1f-b1d7-27bd4ce76966"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/8664caae-1cd6-4c1f-b1d7-27bd4ce76966"/> - <link rel="ostatus:conversation" href="http://pleroma.example.org:4000/contexts/24779b0e-91ad-487e-81bd-6cf5bb437b09"/> - <ostatus:conversation>http://pleroma.example.org:4000/contexts/24779b0e-91ad-487e-81bd-6cf5bb437b09</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/48.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/48.atom"/> - <statusnet:notice_info local_id="48" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=46:objectType=note</id> - <title>New note by lambda</title> - <content type="html">Let's send you an answer.</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/46"/> - <status_net notice_id="46"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T18:05:31+00:00</published> - <updated>2017-04-25T18:05:31+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/89ec2578-3f05-4b04-99b8-3e40f1282491" href="http://pleroma.example.org:4000/objects/89ec2578-3f05-4b04-99b8-3e40f1282491"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/89ec2578-3f05-4b04-99b8-3e40f1282491"/> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=73c7bcf6658f7ce3"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=73c7bcf6658f7ce3</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/46.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/46.atom"/> - <statusnet:notice_info local_id="46" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=44:objectType=note</id> - <title>New note by lambda</title> - <content type="html">Hey.</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/44"/> - <status_net notice_id="44"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T18:01:09+00:00</published> - <updated>2017-04-25T18:01:09+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1" href="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1"/> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=6e7c8fc2823380b4"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=6e7c8fc2823380b4</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/44.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/44.atom"/> - <statusnet:notice_info local_id="44" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=43:objectType=note</id> - <title>New note by lambda</title> - <content type="html">What's coming to you?</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/43"/> - <status_net notice_id="43"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T17:58:41+00:00</published> - <updated>2017-04-25T17:58:41+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1" href="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1"/> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=6e7c8fc2823380b4"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=6e7c8fc2823380b4</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/43.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/43.atom"/> - <statusnet:notice_info local_id="43" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=42:objectType=note</id> - <title>New note by lambda</title> - <content type="html">Now this is podracing.</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/42"/> - <status_net notice_id="42"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T17:57:40+00:00</published> - <updated>2017-04-25T17:57:40+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1" href="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/5047e0a8-2302-483a-a420-ae835f5ca5a1"/> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=6e7c8fc2823380b4"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=6e7c8fc2823380b4</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/42.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/42.atom"/> - <statusnet:notice_info local_id="42" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=39:objectType=note</id> - <title>New note by lambda</title> - <content type="html">Sure looks like it!</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/39"/> - <status_net notice_id="39"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T17:48:27+00:00</published> - <updated>2017-04-25T17:48:27+00:00</updated> - <thr:in-reply-to ref="http://pleroma.example.org:4000/objects/c9fe09c2-7504-46d2-a4f6-44a708455e6f" href="http://pleroma.example.org:4000/objects/c9fe09c2-7504-46d2-a4f6-44a708455e6f"></thr:in-reply-to> - <link rel="related" href="http://pleroma.example.org:4000/objects/c9fe09c2-7504-46d2-a4f6-44a708455e6f"/> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=4c6114a75bb4cea5"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=4c6114a75bb4cea5</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/39.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/39.atom"/> - <statusnet:notice_info local_id="39" source="web"></statusnet:notice_info> -</entry> -<entry> - <id>tag:gs.example.org:4040,2017-04-25:subscription:1:person:6:2017-04-25T17:47:47+00:00</id> - <title>lambda (lambda)'s status on Tuesday, 25-Apr-2017 17:47:47 UTC</title> - <content type="html">&lt;a href=&quot;http://gs.example.org:4040/index.php/lambda&quot;&gt;lambda&lt;/a&gt; started following &lt;a href=&quot;http://pleroma.example.org:4000/users/lain5&quot;&gt;l&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/37"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-04-25T17:47:47+00:00</published> - <updated>2017-04-25T17:47:47+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>http://pleroma.example.org:4000/users/lain5</id> - <title>l</title> - <summary>lambadalambda</summary> - <link rel="alternate" type="text/html" href="http://pleroma.example.org:4000/users/lain5"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://gs.example.org/avatar/6-original-20170425174605.png"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://gs.example.org/avatar/6-96-20170425174605.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://gs.example.org/avatar/6-original-20170425174605.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://gs.example.org/avatar/6-24-20170425174747.png"/> - <poco:preferredUsername>lain5</poco:preferredUsername> - <poco:displayName>l</poco:displayName> - <poco:note>lambadalambda</poco:note> - </activity:object> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=119acad17515314c"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=119acad17515314c</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="http://gs.example.org/index.php/api/statuses/show/37.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/37.atom"/> - <statusnet:notice_info local_id="37" source="activity"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=36:objectType=note</id> - <title>New note by lambda</title> - <content type="html">@&lt;a href=&quot;http://pleroma.example.org:4000/users/lain5&quot; class=&quot;h-card mention&quot;&gt;lain5&lt;/a&gt; Hey, how are you?</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/36"/> - <status_net notice_id="36"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T17:46:22+00:00</published> - <updated>2017-04-25T17:46:22+00:00</updated> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=9c5ec19a18191372"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=9c5ec19a18191372</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="http://pleroma.example.org:4000/users/lain5"/> - <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="http://gs.example.org/index.php/api/statuses/show/36.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/36.atom"/> - <statusnet:notice_info local_id="36" source="web"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.example.org:4040,2017-04-25:noticeId=35:objectType=note</id> - <title>New note by lambda</title> - <content type="html">@lain5@pleroma.example.org does this not work?</content> - <link rel="alternate" type="text/html" href="http://gs.example.org/index.php/notice/35"/> - <status_net notice_id="35"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-25T17:42:31+00:00</published> - <updated>2017-04-25T17:42:31+00:00</updated> - <link rel="ostatus:conversation" href="tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=fc841d7f52caa363"/> - <ostatus:conversation>tag:gs.example.org:4040,2017-04-25:objectType=thread:nonce=fc841d7f52caa363</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="http://gs.example.org/index.php/api/statuses/show/35.atom"/> - <link rel="edit" type="application/atom+xml" href="http://gs.example.org/index.php/api/statuses/show/35.atom"/> - <statusnet:notice_info local_id="35" source="web"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/tesla_mock/https___mamot.fr_users_Skruyb.atom b/test/fixtures/tesla_mock/https___mamot.fr_users_Skruyb.atom @@ -1,342 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://mamot.fr/users/Skruyb.atom</id> - <title>The 7th Son</title> - <subtitle>Fr and En. -Posts will disappear on a regular basis.</subtitle> - <updated>2017-04-28T13:54:23Z</updated> - <logo>https://mamot.fr/system/accounts/avatars/000/026/213/original/d95dbcfc76f77f4c.jpg?1493230984</logo> - <author> - <id>https://mamot.fr/users/Skruyb</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mamot.fr/users/Skruyb</uri> - <name>Skruyb</name> - <email>Skruyb@mamot.fr</email> - <summary type="html">&lt;p&gt;Fr and En.&lt;br /&gt;Posts will disappear on a regular basis.&lt;/p&gt;</summary> - <link rel="alternate" type="text/html" href="https://mamot.fr/@Skruyb"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://mamot.fr/system/accounts/avatars/000/026/213/original/d95dbcfc76f77f4c.jpg?1493230984"/> - <link rel="header" type="image/jpeg" media:width="700" media:height="335" href="https://mamot.fr/system/accounts/headers/000/026/213/original/c1aabdf5c97eb875.jpg?1492797601"/> - <poco:preferredUsername>Skruyb</poco:preferredUsername> - <poco:displayName>The 7th Son</poco:displayName> - <poco:note>Fr and En. -Posts will disappear on a regular basis.</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://mamot.fr/@Skruyb"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb.atom"/> - <link rel="next" type="application/atom+xml" href="https://mamot.fr/users/Skruyb.atom?max_id=175878"/> - <link rel="hub" href="https://mamot.fr/api/push"/> - <link rel="salmon" href="https://mamot.fr/api/salmon/26213"/> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1299665:objectType=Status</id> - <published>2017-05-10T20:06:59Z</published> - <updated>2017-05-10T20:06:59Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="es">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pouets.ovh/@noName" class="u-url mention"&gt;@&lt;span&gt;noName&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Pour comparer faut avoir tester... Ô wait!!! 😁&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pouets.ovh/users/noName"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176780"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176780.atom"/> - <thr:in-reply-to ref="tag:pouets.ovh,2017-05-10:objectId=114198:objectType=Status" href="https://pouets.ovh/users/noName/updates/1174"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1299185:objectType=Status</id> - <published>2017-05-10T19:52:14Z</published> - <updated>2017-05-10T19:52:14Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://witches.town/@Dhveszak" class="u-url mention"&gt;@&lt;span&gt;Dhveszak&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Toi!! Tu vises le ministère de la propagande avoue!!!!!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://witches.town/users/Dhveszak"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176702"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176702.atom"/> - <thr:in-reply-to ref="tag:witches.town,2017-05-10:objectId=1439170:objectType=Status" href="https://witches.town/users/Dhveszak/updates/193318"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1299019:objectType=Status</id> - <published>2017-05-10T19:47:19Z</published> - <updated>2017-05-10T19:47:19Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;Facebook s&amp;apos;attaque aux sites internet &amp;quot;trompeurs&amp;quot;&lt;/p&gt;&lt;p&gt;&lt;a href="http://u.afp.com/4W4z" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;http://&lt;/span&gt;&lt;span class=""&gt;u.afp.com/4W4z&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;J&amp;apos;attends de voir que Facebook s&amp;apos;attaque à lui même... rien qu&amp;apos;à lire leurs conditions générales d&amp;apos;utilisation, le respect de la vie privée...&lt;/p&gt;&lt;p&gt;Charité bien ordonnée... Parfois l&amp;apos;égoïsme aurait du bon.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176668"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176668.atom"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1298889:objectType=Status</id> - <published>2017-05-10T19:43:18Z</published> - <updated>2017-05-10T19:43:18Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://octodon.social/@Balise" class="u-url mention"&gt;@&lt;span&gt;Balise&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Fait comme moi, annonce que tu fais dans le flou artistique et que seuls des esprits éclairés pourront en percevoir la beauté et apprécier. Globalement après ça, tout le monde trouve les photos cool :-p&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://octodon.social/users/Balise"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176641"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176641.atom"/> - <thr:in-reply-to ref="tag:octodon.social,2017-05-10:objectId=1887380:objectType=Status" href="https://octodon.social/users/Balise/updates/115220"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1298728:objectType=Status</id> - <published>2017-05-10T19:38:39Z</published> - <updated>2017-05-10T19:38:39Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="ru">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@applecandy" class="u-url mention"&gt;@&lt;span&gt;applecandy&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Lucky you!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/applecandy"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176608"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176608.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-05-10:objectId=5578123:objectType=Status" href="https://mastodon.social/users/applecandy/updates/2317372"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1298431:objectType=Status</id> - <published>2017-05-10T19:26:32Z</published> - <updated>2017-05-10T19:26:32Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;Est-ce que je suis le seul qui lorsqu&amp;apos;il commence à compter les arbres sur le bord de la route n&amp;apos;arrive pas à s&amp;apos;arrêter de compter?&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176561"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176561.atom"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1298224:objectType=Status</id> - <published>2017-05-10T19:18:17Z</published> - <updated>2017-05-10T19:18:17Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;Ca y est j&amp;apos;ai une nouvelle passion. Mettre les bouchons qui trainent par terre dans le bons sens avec mon pied 🙌&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176536"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176536.atom"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1297450:objectType=Status</id> - <published>2017-05-10T18:53:37Z</published> - <updated>2017-05-10T18:53:37Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;Ok. On est capable d&amp;apos;envoyer des mecs dans l&amp;apos;espace, avoir des voitures autonomes, des trucs intelligents de partout mais pas tous les bâtiments accessibles aux personnes à mobilité réduite, les émissions sur le services publics avec une personne faisant la traduction pour les sourds et malentendants de manière systématique...&lt;/p&gt;&lt;p&gt;J&amp;apos;ai du louper un truc dans l&amp;apos;ordre des priorités Oo&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176412"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176412.atom"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1297292:objectType=Status</id> - <published>2017-05-10T18:48:17Z</published> - <updated>2017-05-10T18:48:17Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;J&amp;apos;ai comme envie de faire un truc mais je ne sais pas quoi mais pourtant c&amp;apos;est comme si je ressentais l&amp;apos;idée dans ma tête mais c&amp;apos;est pas clair...&lt;/p&gt;&lt;p&gt;Fuck!!! J&amp;apos;vais aller draguer Josiane à la compta ça va me changer les idées!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176387"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176387.atom"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1296598:objectType=Status</id> - <published>2017-05-10T18:25:11Z</published> - <updated>2017-05-10T18:25:11Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mamot.fr/@Smeablog" class="u-url mention"&gt;@&lt;span&gt;Smeablog&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Pas faux MDR!!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mamot.fr/users/Smeablog"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176320"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176320.atom"/> - <thr:in-reply-to ref="tag:mamot.fr,2017-05-10:objectId=1296591:objectType=Status" href="https://mamot.fr/@Smeablog/1296591"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1296571:objectType=Status</id> - <published>2017-05-10T18:24:13Z</published> - <updated>2017-05-10T18:24:13Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mamot.fr/@Smeablog" class="u-url mention"&gt;@&lt;span&gt;Smeablog&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Ca ne change pas la finalité malheureusement, ça ne m&amp;apos;ouvre pas ce à quoi je veux accéder 😭&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mamot.fr/users/Smeablog"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176315"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176315.atom"/> - <thr:in-reply-to ref="tag:mamot.fr,2017-05-10:objectId=1296531:objectType=Status" href="https://mamot.fr/@Smeablog/1296531"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1296475:objectType=Status</id> - <published>2017-05-10T18:20:50Z</published> - <updated>2017-05-10T18:20:50Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;Arrrgghhhhhhh!!!!&lt;/p&gt;&lt;p&gt;Quand t&amp;apos;es sur le point de cliquer sur un lien dans le fil public global et que BOOM ça se met à jour... J&amp;apos;ose même pas imaginer combien j&amp;apos;ai ouvert de pages web sans le vouloir!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176298"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176298.atom"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1296426:objectType=Status</id> - <published>2017-05-10T18:19:17Z</published> - <updated>2017-05-10T18:19:17Z</updated> - <title>Skruyb shared a status by Isaluini@mastodon.social</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:mastodon.social,2017-05-10:objectId=5587049:objectType=Status</id> - <published>2017-05-10T18:18:59Z</published> - <updated>2017-05-10T18:19:00Z</updated> - <title>New status by Isaluini@mastodon.social</title> - <author> - <id>https://mastodon.social/users/Isaluini</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/Isaluini</uri> - <name>Isaluini</name> - <email>Isaluini@mastodon.social</email> - <summary type="html">&lt;p&gt;Adicciones: Escribir, diseñar, cine, café, humor negro, música y dibujar. | Jedi. Bueno, no. Algún día (?) | Gratitude.&lt;/p&gt;</summary> - <link rel="alternate" type="text/html" href="https://mastodon.social/@Isaluini"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://mamot.fr/system/accounts/avatars/000/027/466/original/6c4659e795647240.jpg?1493580262"/> - <link rel="header" type="image/jpeg" media:width="700" media:height="335" href="https://mamot.fr/system/accounts/headers/000/027/466/original/608989b32a3efe1b.jpg?1493580262"/> - <poco:preferredUsername>Isaluini</poco:preferredUsername> - <poco:displayName>Isa</poco:displayName> - <poco:note>Adicciones: Escribir, diseñar, cine, café, humor negro, música y dibujar. | Jedi. Bueno, no. Algún día (?) | Gratitude.</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="ru">&lt;p&gt;♫ &lt;br&gt;&lt;a href="https://www.youtube.com/watch?v=pT68FS3YbQ4"&gt;&lt;span class="invisible"&gt;https://www.&lt;/span&gt;&lt;span class="ellipsis"&gt;youtube.com/watch?v=pT68FS3YbQ&lt;/span&gt;&lt;span class="invisible"&gt;4&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/Isaluini/updates/2318469"/> - </activity:object> - <content type="html" xml:lang="en">&lt;p&gt;♫ &lt;br&gt;&lt;a href="https://www.youtube.com/watch?v=pT68FS3YbQ4"&gt;&lt;span class="invisible"&gt;https://www.&lt;/span&gt;&lt;span class="ellipsis"&gt;youtube.com/watch?v=pT68FS3YbQ&lt;/span&gt;&lt;span class="invisible"&gt;4&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176292"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176292.atom"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1295893:objectType=Status</id> - <published>2017-05-10T18:01:51Z</published> - <updated>2017-05-10T18:01:51Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mamot.fr/@Chat2Gouttieres" class="u-url mention"&gt;@&lt;span&gt;Chat2Gouttieres&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Ah bah après faut savoir mettre à profit ce savoir ^^&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mamot.fr/users/Chat2Gouttieres"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176203"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176203.atom"/> - <thr:in-reply-to ref="tag:mamot.fr,2017-05-10:objectId=1295869:objectType=Status" href="https://mamot.fr/@Chat2Gouttieres/1295869"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1295815:objectType=Status</id> - <published>2017-05-10T18:00:02Z</published> - <updated>2017-05-10T18:00:02Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mamot.fr/@Chat2Gouttieres" class="u-url mention"&gt;@&lt;span&gt;Chat2Gouttieres&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Exactement. On a les jeux mais pas le pain encore.&lt;/p&gt;&lt;p&gt;Finalement on a rien inventé :-p&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mamot.fr/users/Chat2Gouttieres"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176182"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176182.atom"/> - <thr:in-reply-to ref="tag:mamot.fr,2017-05-10:objectId=1295800:objectType=Status" href="https://mamot.fr/@Chat2Gouttieres/1295800"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1295778:objectType=Status</id> - <published>2017-05-10T17:58:52Z</published> - <updated>2017-05-10T17:58:52Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mamot.fr/@Chat2Gouttieres" class="u-url mention"&gt;@&lt;span&gt;Chat2Gouttieres&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;C&amp;apos;est ça visiblement dans notre société dite moderne... &amp;quot;Créer l&amp;apos;illusion que&amp;quot; Oo.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mamot.fr/users/Chat2Gouttieres"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176174"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176174.atom"/> - <thr:in-reply-to ref="tag:mamot.fr,2017-05-10:objectId=1295765:objectType=Status" href="https://mamot.fr/@Chat2Gouttieres/1295765"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1294943:objectType=Status</id> - <published>2017-05-10T17:31:44Z</published> - <updated>2017-05-10T17:31:44Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <summary xml:lang="it">Hey.</summary> - <content type="html" xml:lang="it">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@lambadalambda" class="u-url mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Hey!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/lambadalambda"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176041"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176041.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-05-10:objectId=5582979:objectType=Status" href="https://mastodon.social/users/lambadalambda/updates/2317991"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1294914:objectType=Status</id> - <published>2017-05-10T17:30:40Z</published> - <updated>2017-05-10T17:30:40Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mamot.fr/@EloClemTiti" class="u-url mention"&gt;@&lt;span&gt;EloClemTiti&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;J&amp;apos;ai souvent cette impression en effet 😂&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mamot.fr/users/EloClemTiti"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/176034"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/176034.atom"/> - <thr:in-reply-to ref="tag:mamot.fr,2017-05-10:objectId=1294608:objectType=Status" href="https://mamot.fr/@EloClemTiti/1294608"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1294148:objectType=Status</id> - <published>2017-05-10T17:02:01Z</published> - <updated>2017-05-10T17:02:01Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;Les gars, les boss veulent voir de l&amp;apos;avancement!! Une idée?&lt;/p&gt;&lt;p&gt;On fait comme d&amp;apos;habitude. On divise nos tâches en 25.000 tâches unitaires, on fout du vert au maximum et on crée l&amp;apos;illusion que ça a bien avancé!&lt;/p&gt;&lt;p&gt;Deal!!&lt;/p&gt;&lt;p&gt;Bob, tu choisis quel vert on utilise&lt;br /&gt;Alice, t&amp;apos;es en charge de la typo&lt;br /&gt;Moi, je m&amp;apos;occupe qu&amp;apos;on prend bien le dernier template ppt fournit par la comm interne.&lt;/p&gt;&lt;p&gt;Des winners qu&amp;apos;on est!!!! Des WI-NNERS!!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/175898"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/175898.atom"/> - </entry> - <entry> - <id>tag:mamot.fr,2017-05-10:objectId=1293995:objectType=Status</id> - <published>2017-05-10T16:57:53Z</published> - <updated>2017-05-10T16:57:53Z</updated> - <title>New status by Skruyb</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="ru">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://mastodon.social/@SauceHair" class="u-url mention"&gt;@&lt;span&gt;SauceHair&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Cool!!&lt;/p&gt;&lt;p&gt;Bon courage.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/SauceHair"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mamot.fr/users/Skruyb/updates/175878"/> - <link rel="self" type="application/atom+xml" href="https://mamot.fr/users/Skruyb/updates/175878.atom"/> - <thr:in-reply-to ref="tag:mastodon.social,2017-05-10:objectId=5579955:objectType=Status" href="https://mastodon.social/users/SauceHair/updates/2317615"/> - </entry> -</feed> diff --git a/test/fixtures/tesla_mock/https___mastodon.social_users_lambadalambda.atom b/test/fixtures/tesla_mock/https___mastodon.social_users_lambadalambda.atom @@ -1,464 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://mastodon.social/users/lambadalambda.atom</id> - <title>Critical Value</title> - <subtitle></subtitle> - <updated>2017-04-16T21:47:25Z</updated> - <logo>https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif</logo> - <author> - <id>https://mastodon.social/users/lambadalambda</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/lambadalambda</uri> - <name>lambadalambda</name> - <email>lambadalambda@mastodon.social</email> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="avatar" type="image/gif" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Critical Value</poco:displayName> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://mastodon.social/@lambadalambda"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda.atom"/> - <link rel="next" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda.atom?max_id=1616358"/> - <link rel="hub" href="https://mastodon.social/api/push"/> - <link rel="salmon" href="https://mastodon.social/api/salmon/264"/> - <entry> - <id>tag:mastodon.social,2017-05-04:objectId=4991300:objectType=Status</id> - <published>2017-05-04T14:10:30Z</published> - <updated>2017-05-04T14:10:30Z</updated> - <title>Delete</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/delete</activity:verb> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2247090"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2247090.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-04:objectId=4980289:objectType=Status</id> - <published>2017-05-04T07:43:23Z</published> - <updated>2017-05-04T07:43:23Z</updated> - <title>Delete</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/delete</activity:verb> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2244602"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2244602.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-03:objectId=4952899:objectType=Status</id> - <published>2017-05-03T17:26:43Z</published> - <updated>2017-05-03T17:26:43Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; OK!!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2237124"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2237124.atom"/> - <thr:in-reply-to ref="https://pleroma.soykaf.com/objects/5e755d92-f0ee-432f-8c17-590962aea59c" href=""/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-03:objectId=4952810:objectType=Status</id> - <published>2017-05-03T17:24:34Z</published> - <updated>2017-05-03T17:24:34Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="el">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; yeah :)&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2237089"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2237089.atom"/> - <thr:in-reply-to ref="https://pleroma.soykaf.com/objects/32ff0743-236a-41e5-81c5-a3211088e741" href=""/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-03:objectId=4950388:objectType=Status</id> - <published>2017-05-03T16:22:00Z</published> - <updated>2017-05-03T16:22:00Z</updated> - <title>lambadalambda shared a status by lambadalambda@social.heldscal.la</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:social.heldscal.la,2017-05-03:noticeId=2030733:objectType=note</id> - <published>2017-05-03T12:29:20Z</published> - <updated>2017-05-03T12:29:31Z</updated> - <title>New status by lambadalambda@social.heldscal.la</title> - <author> - <id>https://social.heldscal.la/user/23211</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://social.heldscal.la/user/23211</uri> - <name>lambadalambda</name> - <email>lambadalambda@social.heldscal.la</email> - <summary type="html">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="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/236/original/23211-original-20170416114255.jpeg"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Constance Variable</poco:displayName> - <poco:note>Call me Deacon Blues.</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">Time for work. &lt;a href="https://social.heldscal.la/file/953c117a1e7e4c763755d2ac29cf1aae08e025599f4a4cc11ddff4082c07f969.jpg"&gt;https://social.heldscal.la/attachment/120552&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" type="image/jpeg" length="383072" href="https://files.mastodon.social/media_attachments/files/000/391/513/original/953c117a1e7e4c763755d2ac29cf1aae08e025599f4a4cc11ddff4082c07f969.jpg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2030733"/> - </activity:object> - <content type="html" xml:lang="en">Time for work. &lt;a href="https://social.heldscal.la/file/953c117a1e7e4c763755d2ac29cf1aae08e025599f4a4cc11ddff4082c07f969.jpg"&gt;https://social.heldscal.la/attachment/120552&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2236405"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2236405.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-03:objectId=4934452:objectType=Status</id> - <published>2017-05-03T08:21:09Z</published> - <updated>2017-05-03T08:21:09Z</updated> - <title>lambadalambda shared a status by lain@pleroma.soykaf.com</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>https://pleroma.soykaf.com/objects/4c1bda26-902e-4525-9fcd-b9fd44925193</id> - <published>2017-05-03T08:04:44Z</published> - <updated>2017-05-03T08:05:52Z</updated> - <title>New status by lain@pleroma.soykaf.com</title> - <author> - <id>https://pleroma.soykaf.com/users/lain</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://pleroma.soykaf.com/users/lain</uri> - <name>lain</name> - <email>lain@pleroma.soykaf.com</email> - <summary type="html">Test account</summary> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/125/902/original/6B3AFC74ACA841B24CFB94DB9044C84EDE6AFF31C71718B023D413DAED09A68E.jpeg"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lain</poco:preferredUsername> - <poco:displayName>Lain Iwakura</poco:displayName> - <poco:note>Test account</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href=""/> - </activity:object> - <content type="html" xml:lang="en">Added returning the entries as xml... let's see if the mastodon hammering stops now.</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2232660"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2232660.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-02:objectId=4905499:objectType=Status</id> - <published>2017-05-02T19:34:21Z</published> - <updated>2017-05-02T19:34:21Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="ru">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; yay!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2226006"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2226006.atom"/> - <thr:in-reply-to ref="https://pleroma.soykaf.com/objects/b79fa9cd-1d27-448a-844f-79f306bc75c9" href=""/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-02:objectId=4905442:objectType=Status</id> - <published>2017-05-02T19:33:33Z</published> - <updated>2017-05-02T19:33:33Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fa">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; so?&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2225992"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2225992.atom"/> - <thr:in-reply-to ref="https://pleroma.soykaf.com/objects/233a878a-974e-4e75-b1c8-aa7657f561fc" href=""/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-02:objectId=4901603:objectType=Status</id> - <published>2017-05-02T18:33:06Z</published> - <updated>2017-05-02T18:33:06Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="el">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; hey&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2224923"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2224923.atom"/> - <thr:in-reply-to ref="https://pleroma.soykaf.com/objects/c237d966-ac75-4fe3-a87a-d89d71a3a7a4" href=""/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-01:objectId=4836720:objectType=Status</id> - <published>2017-05-01T18:52:16Z</published> - <updated>2017-05-01T18:52:16Z</updated> - <title>lambadalambda shared a status by lain@pleroma.soykaf.com</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>https://pleroma.soykaf.com/objects/7b41bb51-9aba-436a-82d9-dd3f5aca98c9</id> - <published>2017-05-01T18:50:54Z</published> - <updated>2017-05-01T18:50:57Z</updated> - <title>New status by lain@pleroma.soykaf.com</title> - <author> - <id>https://pleroma.soykaf.com/users/lain</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://pleroma.soykaf.com/users/lain</uri> - <name>lain</name> - <email>lain@pleroma.soykaf.com</email> - <summary type="html">Test account</summary> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/125/902/original/6B3AFC74ACA841B24CFB94DB9044C84EDE6AFF31C71718B023D413DAED09A68E.jpeg"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lain</poco:preferredUsername> - <poco:displayName>Lain Iwakura</poco:displayName> - <poco:note>Test account</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;a href="https://mastodon.social/users/lambadalambda"&gt;@lambadalambda@mastodon.social&lt;/a&gt; you're an all-star.</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/lambadalambda"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href=""/> - <thr:in-reply-to ref="tag:mastodon.social,2017-05-01:objectId=4836142:objectType=Status" href="https://mastodon.social/@lambadalambda/4836142"/> - </activity:object> - <content type="html" xml:lang="en">&lt;a href="https://mastodon.social/users/lambadalambda"&gt;@lambadalambda@mastodon.social&lt;/a&gt; you're an all-star.</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2211632"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2211632.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-01:objectId=4836142:objectType=Status</id> - <published>2017-05-01T18:38:47Z</published> - <updated>2017-05-01T18:38:47Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="ru">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Hey now!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2211518"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2211518.atom"/> - <thr:in-reply-to ref="https://pleroma.soykaf.com/objects/ffae4bea-00a3-4cef-8076-4ee4d448cb46" href=""/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-01:objectId=4836055:objectType=Status</id> - <published>2017-05-01T18:37:04Z</published> - <updated>2017-05-01T18:37:04Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="el">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; hello&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2211496"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2211496.atom"/> - <thr:in-reply-to ref="https://pleroma.soykaf.com/objects/ffae4bea-00a3-4cef-8076-4ee4d448cb46" href=""/> - </entry> - <entry> - <id>tag:mastodon.social,2017-05-01:objectId=4834850:objectType=Status</id> - <published>2017-05-01T18:10:43Z</published> - <updated>2017-05-01T18:10:43Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="el">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Hey!&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2211256"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2211256.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-29:objectId=4694455:objectType=Status</id> - <published>2017-04-29T18:39:12Z</published> - <updated>2017-04-29T18:39:12Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="ru">&lt;p&gt;@lain@pleroma.soykaf.com What&amp;apos;s up?&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2189604"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2189604.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-29:objectId=4694384:objectType=Status</id> - <published>2017-04-29T18:37:32Z</published> - <updated>2017-04-29T18:37:32Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="fr">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://social.heldscal.la/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Hey.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/37181"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2189588"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/2189588.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-07:objectId=1874242:objectType=Status</id> - <published>2017-04-07T11:02:56Z</published> - <updated>2017-04-07T11:02:56Z</updated> - <title>lambadalambda shared a status by 0xroy@social.wxcafe.net</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:social.wxcafe.net,2017-04-07:objectId=72554:objectType=Status</id> - <published>2017-04-07T11:01:59Z</published> - <updated>2017-04-07T11:02:00Z</updated> - <title>New status by 0xroy@social.wxcafe.net</title> - <author> - <id>https://social.wxcafe.net/users/0xroy</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://social.wxcafe.net/users/0xroy</uri> - <name>0xroy</name> - <email>0xroy@social.wxcafe.net</email> - <summary type="html">ta caution weeb | discussions privées : &lt;a href="https://%F0%9F%92%8C.0xroy.me"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class=""&gt;💌.0xroy.me&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt;</summary> - <link rel="alternate" type="text/html" href="https://social.wxcafe.net/@0xroy"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/036/953/original/20068e41d0310172.jpg"/> - <link rel="header" type="image/jpeg" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/036/953/original/2229d0e3f129fe8c.jpg"/> - <poco:preferredUsername>0xroy</poco:preferredUsername> - <poco:displayName>「R O Y 🍵 B O S」</poco:displayName> - <poco:note>ta caution weeb | discussions privées : https://💌.0xroy.me</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;someone pls eli5 matrix (protocol) and riot&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://social.wxcafe.net/users/0xroy/updates/4510"/> - </activity:object> - <content type="html" xml:lang="en">&lt;p&gt;someone pls eli5 matrix (protocol) and riot&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1689208"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1689208.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-06:objectId=1768247:objectType=Status</id> - <published>2017-04-06T11:10:19Z</published> - <updated>2017-04-06T11:10:19Z</updated> - <title>lambadalambda shared a status by areyoutoo@mastodon.xyz</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:mastodon.xyz,2017-04-05:objectId=133327:objectType=Status</id> - <published>2017-04-05T17:36:41Z</published> - <updated>2017-04-05T18:12:14Z</updated> - <title>New status by areyoutoo@mastodon.xyz</title> - <author> - <id>https://mastodon.xyz/users/areyoutoo</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.xyz/users/areyoutoo</uri> - <name>areyoutoo</name> - <email>areyoutoo@mastodon.xyz</email> - <summary type="html">devops | retired gamedev | always boost puppy pics</summary> - <link rel="alternate" type="text/html" href="https://mastodon.xyz/@areyoutoo"/> - <link rel="avatar" type="image/png" media:width="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/047/888/original/5ce2e132d4c18d65.png"/> - <link rel="header" type="image/png" media:width="700" media:height="335" href="https://files.mastodon.social/accounts/headers/000/047/888/original/missing.png"/> - <poco:preferredUsername>areyoutoo</poco:preferredUsername> - <poco:displayName>Raw Butter</poco:displayName> - <poco:note>devops | retired gamedev | always boost puppy pics</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;Some UX thoughts for &lt;a href="https://mastodon.xyz/tags/mastodev"&gt;#&lt;span&gt;mastodev&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;- Would be nice if I could work on multiple draft toots? Clicking to reply to someone seems to erase any draft I had been working on.&lt;/p&gt;&lt;p&gt;- Kinda risky to click on the Federated Timeline if it loads new toots and scrolls 10ms before I click on something.&lt;/p&gt;&lt;p&gt;I probably don't know enough web frontend to help, but it might be fun to try.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="mastodev"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.xyz/users/areyoutoo/updates/36028"/> - </activity:object> - <content type="html" xml:lang="en">&lt;p&gt;Some UX thoughts for &lt;a href="https://mastodon.xyz/tags/mastodev"&gt;#&lt;span&gt;mastodev&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;- Would be nice if I could work on multiple draft toots? Clicking to reply to someone seems to erase any draft I had been working on.&lt;/p&gt;&lt;p&gt;- Kinda risky to click on the Federated Timeline if it loads new toots and scrolls 10ms before I click on something.&lt;/p&gt;&lt;p&gt;I probably don't know enough web frontend to help, but it might be fun to try.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1658950"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1658950.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-06:objectId=1764509:objectType=Status</id> - <published>2017-04-06T10:15:38Z</published> - <updated>2017-04-06T10:15:38Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <summary xml:lang="en">This is a test for cw federation</summary> - <content type="html" xml:lang="en">&lt;p&gt;This is a test for cw federation body text.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1657819"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1657819.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-05:objectId=1645208:objectType=Status</id> - <published>2017-04-05T07:14:53Z</published> - <updated>2017-04-05T07:14:53Z</updated> - <title>lambadalambda shared a status by lambadalambda@social.heldscal.la</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <activity:object> - <id>tag:social.heldscal.la,2017-04-05:noticeId=1502088:objectType=note</id> - <published>2017-04-05T06:12:09Z</published> - <updated>2017-04-05T07:12:47Z</updated> - <title>New status by lambadalambda@social.heldscal.la</title> - <author> - <id>https://social.heldscal.la/user/23211</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://social.heldscal.la/user/23211</uri> - <name>lambadalambda</name> - <email>lambadalambda@social.heldscal.la</email> - <summary type="html">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="120" media:height="120" href="https://files.mastodon.social/accounts/avatars/000/000/236/original/23211-original-20170416114255.jpeg"/> - <link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/> - <poco:preferredUsername>lambadalambda</poco:preferredUsername> - <poco:displayName>Constance Variable</poco:displayName> - <poco:note>Call me Deacon Blues.</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">Federation 101: &lt;a href="https://www.youtube.com/watch?v=t1lYU5CA40o"&gt;https://www.youtube.com/watch?v=t1lYU5CA40o&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1502088"/> - </activity:object> - <content type="html" xml:lang="en">Federation 101: &lt;a href="https://www.youtube.com/watch?v=t1lYU5CA40o"&gt;https://www.youtube.com/watch?v=t1lYU5CA40o&lt;/a&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1618003"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1618003.atom"/> - </entry> - <entry> - <id>tag:mastodon.social,2017-04-05:objectId=1641750:objectType=Status</id> - <published>2017-04-05T05:44:48Z</published> - <updated>2017-04-05T05:44:48Z</updated> - <title>New status by lambadalambda</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://social.heldscal.la/lambadalambda" class="u-url mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; just a test.&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/23211"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/lambadalambda/updates/1616358"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/lambadalambda/updates/1616358.atom"/> - </entry> -</feed> diff --git a/test/fixtures/tesla_mock/https___osada.macgirvin.com_channel_mike.json b/test/fixtures/tesla_mock/https___osada.macgirvin.com_channel_mike.json @@ -8,6 +8,7 @@ "preferredUsername": "mike", "name": "Mike Macgirvin (Osada)", "updated": "2018-08-29T03:09:11Z", + "discoverable": "true", "icon": { "type": "Image", "mediaType": "image/jpeg", @@ -51,4 +52,4 @@ "created": "2018-10-17T07:16:28Z", "signatureValue": "WbfFVIPImkd3yNu6brz0CvZaeV242rwAbH0vy8DM4vfnXCxLr5Uv/Wj9gwP+tbooTxGaahAKBeqlGkQp8RLEo37LATrKMRLA/0V6DeeV+C5ORWR9B4WxyWiD3s/9Wf+KesFMtktNLAcMZ5PfnOS/xNYerhnpkp/gWPxtkglmLIWJv+w18A5zZ01JCxsO4QljHbhYaEUPHUfQ97abrkLECeam+FThVwdO6BFCtbjoNXHfzjpSZL/oKyBpi5/fpnqMqOLOQPs5WgBBZJvjEYYkQcoPTyxYI5NGpNbzIjGHPQNuACnOelH16A7L+q4swLWDIaEFeXQ2/5bmqVKZDZZ6usNP4QyTVszwd8jqo27qcDTNibXDUTsTdKpNQvM/3UncBuzuzmUV3FczhtGshIU1/pRVZiQycpVqPlGLvXhP/yZCe+1siyqDd+3uMaS2vkHTObSl5r+VYof+c+TcjrZXHSWnQTg8/X3zkoBWosrQ93VZcwjzMxQoARYv6rphbOoTz7RPmGAXYUt3/PDWkqDlmQDwCpLNNkJo1EidyefZBdD9HXQpCBO0ZU0NHb0JmPvg/+zU0krxlv70bm3RHA/maBETVjroIWzt7EwQEg5pL2hVnvSBG+1wF3BtRVe77etkPOHxLnYYIcAMLlVKCcgDd89DPIziQyruvkx1busHI08=" } -} +} +\ No newline at end of file diff --git a/test/fixtures/tesla_mock/https___pawoo.net_users_pekorino.atom b/test/fixtures/tesla_mock/https___pawoo.net_users_pekorino.atom @@ -1,231 +0,0 @@ -<?xml version="1.0"?> -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0"> - <id>https://pawoo.net/users/pekorino.atom</id> - <title>モノエ</title> - <subtitle>シアトル・米国 - -GNUsocial 英語版 -http://shitposter.club/mono - -</subtitle> - <updated>2017-05-07T09:28:20Z</updated> - <logo>https://img.pawoo.net/accounts/avatars/000/128/378/original/e1fce04a36a1ad90.jpg</logo> - <author> - <id>https://pawoo.net/users/pekorino</id> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://pawoo.net/users/pekorino</uri> - <name>pekorino</name> - <email>pekorino@pawoo.net</email> - <summary type="html">&lt;p&gt;シアトル・米国&lt;/p&gt;&lt;p&gt;GNUsocial 英語版&lt;br /&gt;&lt;a href="http://shitposter.club/mono" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;http://&lt;/span&gt;&lt;span class=""&gt;shitposter.club/mono&lt;/span&gt;&lt;span class="invisible"&gt;&lt;/span&gt;&lt;/a&gt; &lt;/p&gt;</summary> - <link rel="alternate" type="text/html" href="https://pawoo.net/@pekorino"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://img.pawoo.net/accounts/avatars/000/128/378/original/e1fce04a36a1ad90.jpg"/> - <link rel="header" type="image/png" media:width="700" media:height="335" href="https://img.pawoo.net/accounts/headers/000/128/378/original/bae3502120206e68.png"/> - <poco:preferredUsername>pekorino</poco:preferredUsername> - <poco:displayName>モノエ</poco:displayName> - <poco:note>シアトル・米国 - -GNUsocial 英語版 -http://shitposter.club/mono - -</poco:note> - <mastodon:scope>public</mastodon:scope> - </author> - <link rel="alternate" type="text/html" href="https://pawoo.net/@pekorino"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino.atom"/> - <link rel="hub" href="https://pawoo.net/api/push"/> - <link rel="salmon" href="https://pawoo.net/api/salmon/128378"/> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9319211:objectType=Status</id> - <published>2017-05-07T09:56:35Z</published> - <updated>2017-05-07T09:56:35Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/moonman" class="u-url mention"&gt;@&lt;span&gt;moonman&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/rw" class="u-url mention"&gt;@&lt;span&gt;rw&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class="h-card"&gt;&lt;a href="https://social.heldscal.la/lambadalambda" class="u-url mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/mono" class="u-url mention"&gt;@&lt;span&gt;mono&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;/p&gt;&lt;p&gt;i have to wait for someone to respond to this before i can follow because i dont think this software has a direct follow by url option&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9056"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/23211"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/666"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/1"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2496950"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2496950.atom"/> - <thr:in-reply-to ref="tag:pawoo.net,2017-05-07:objectId=9318595:objectType=Status" href="https://pawoo.net/@pekorino/9318595"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9318595:objectType=Status</id> - <published>2017-05-07T09:54:39Z</published> - <updated>2017-05-07T09:54:39Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/mono" class="u-url mention"&gt;@&lt;span&gt;mono&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class="h-card"&gt;&lt;a href="https://social.heldscal.la/lambadalambda" class="u-url mention"&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/rw" class="u-url mention"&gt;@&lt;span&gt;rw&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/moonman" class="u-url mention"&gt;@&lt;span&gt;moonman&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;br /&gt;please respond&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/1"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/666"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/23211"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9056"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2496838"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2496838.atom"/> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-07:noticeId=2856143:objectType=note" href="https://shitposter.club/notice/2856143"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9313978:objectType=Status</id> - <published>2017-05-07T09:39:17Z</published> - <updated>2017-05-07T09:39:17Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/moonman" class="u-url mention"&gt;@&lt;span&gt;moonman&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;br /&gt;mastodon is so slow. browser crashed twice trying to set avatar&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/1"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2496065"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2496065.atom"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9312691:objectType=Status</id> - <published>2017-05-07T09:34:38Z</published> - <updated>2017-05-07T09:34:38Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/hardbass2k8" class="u-url mention"&gt;@&lt;span&gt;hardbass2k8&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;a href="https://pawoo.net/media/mZJjLpbPU72GFEz2Svk" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class="ellipsis"&gt;pawoo.net/media/mZJjLpbPU72GFE&lt;/span&gt;&lt;span class="invisible"&gt;z2Svk&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9591"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" type="image/jpeg" length="42074" href="https://img.pawoo.net/media_attachments/files/000/681/737/original/483a0d76fce39156.jpg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2495835"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2495835.atom"/> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-07:noticeId=2855897:objectType=note" href="https://shitposter.club/notice/2855897"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9312379:objectType=Status</id> - <published>2017-05-07T09:33:29Z</published> - <updated>2017-05-07T09:33:29Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/hardbass2k8" class="u-url mention"&gt;@&lt;span&gt;hardbass2k8&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;a href="https://pawoo.net/media/nt5JHBEHyTN2bqzdcGU" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class="ellipsis"&gt;pawoo.net/media/nt5JHBEHyTN2bq&lt;/span&gt;&lt;span class="invisible"&gt;zdcGU&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9591"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" type="image/png" length="8605" href="https://img.pawoo.net/media_attachments/files/000/681/714/original/1e3f216d4f78c69d.png"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2495772"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2495772.atom"/> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-07:noticeId=2855886:objectType=comment" href="https://shitposter.club/notice/2855886"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9311765:objectType=Status</id> - <published>2017-05-07T09:31:26Z</published> - <updated>2017-05-07T09:31:26Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;a href="https://pawoo.net/media/C4RV6ubsEtvS04DX6qs" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class="ellipsis"&gt;pawoo.net/media/C4RV6ubsEtvS04&lt;/span&gt;&lt;span class="invisible"&gt;DX6qs&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" type="image/jpeg" length="71196" href="https://img.pawoo.net/media_attachments/files/000/681/667/original/dc310e8fd312e7ff.jpg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2495666"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2495666.atom"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9311610:objectType=Status</id> - <published>2017-05-07T09:30:59Z</published> - <updated>2017-05-07T09:30:59Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;a href="https://pawoo.net/media/MBmkeEdrjs8pAtCHN6s" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class="ellipsis"&gt;pawoo.net/media/MBmkeEdrjs8pAt&lt;/span&gt;&lt;span class="invisible"&gt;CHN6s&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" type="image/jpeg" length="158377" href="https://img.pawoo.net/media_attachments/files/000/681/656/original/7e2d78ecfd243e67.jpg"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2495632"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2495632.atom"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9307782:objectType=Status</id> - <published>2017-05-07T09:16:47Z</published> - <updated>2017-05-07T09:16:47Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/mono" class="u-url mention"&gt;@&lt;span&gt;mono&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;test&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9056"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2494966"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2494966.atom"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9307444:objectType=Status</id> - <published>2017-05-07T09:15:42Z</published> - <updated>2017-05-07T09:15:42Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/hardbass2k8" class="u-url mention"&gt;@&lt;span&gt;hardbass2k8&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; テスト&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9591"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2494900"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2494900.atom"/> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-07:noticeId=2855867:objectType=note" href="https://shitposter.club/notice/2855867"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-05-07:objectId=9307239:objectType=Status</id> - <published>2017-05-07T09:14:58Z</published> - <updated>2017-05-07T09:14:58Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;ててててててテスト&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/2494866"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/2494866.atom"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-04-20:objectId=2212164:objectType=Status</id> - <published>2017-04-20T06:19:18Z</published> - <updated>2017-04-20T06:19:18Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://shitposter.club/mono" class="u-url mention"&gt;@&lt;span&gt;mono&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;a href="https://pawoo.net/media/iMbjMBVPfZJX3lUC2Sc" rel="nofollow noopener" target="_blank"&gt;&lt;span class="invisible"&gt;https://&lt;/span&gt;&lt;span class="ellipsis"&gt;pawoo.net/media/iMbjMBVPfZJX3l&lt;/span&gt;&lt;span class="invisible"&gt;UC2Sc&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9056"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" type="image/png" length="754410" href="https://img.pawoo.net/media_attachments/files/000/199/926/original/f11a4c9c91403766.png"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/874763"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/874763.atom"/> - <thr:in-reply-to ref="tag:shitposter.club,2017-04-20:noticeId=2570261:objectType=note" href="https://shitposter.club/notice/2570261"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-04-20:objectId=2206216:objectType=Status</id> - <published>2017-04-20T05:57:59Z</published> - <updated>2017-04-20T05:57:59Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;テスト&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/872900"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/872900.atom"/> - </entry> - <entry> - <id>tag:pawoo.net,2017-04-20:objectId=2204702:objectType=Status</id> - <published>2017-04-20T05:52:09Z</published> - <updated>2017-04-20T05:52:09Z</updated> - <title>New status by pekorino</title> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <content type="html" xml:lang="en">&lt;p&gt;HELLOWORLD&lt;/p&gt;</content> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <mastodon:scope>public</mastodon:scope> - <link rel="alternate" type="text/html" href="https://pawoo.net/users/pekorino/updates/872464"/> - <link rel="self" type="application/atom+xml" href="https://pawoo.net/users/pekorino/updates/872464.atom"/> - </entry> -</feed> diff --git a/test/fixtures/tesla_mock/https___pleroma.soykaf.com_users_lain_feed.atom.xml b/test/fixtures/tesla_mock/https___pleroma.soykaf.com_users_lain_feed.atom.xml @@ -1 +0,0 @@ -<?xml version="1.0"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0"><id>https://pleroma.soykaf.com/users/lain/feed.atom</id><title>lain's timeline</title><updated>2017-05-05T08:38:03.385598</updated><link rel="hub" href="https://pleroma.soykaf.com/push/hub/lain"/><link rel="salmon" href="https://pleroma.soykaf.com/users/lain/salmon"/><link rel="self" href="https://pleroma.soykaf.com/users/lain/feed.atom" type="application/atom+xml"/><author><id>https://pleroma.soykaf.com/users/lain</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://pleroma.soykaf.com/users/lain</uri><poco:preferredUsername>lain</poco:preferredUsername><poco:displayName>Lain Iwakura</poco:displayName><poco:note>Test account</poco:note><name>lain</name><link rel="avatar" href="https://pleroma.soykaf.com/media/dbd1aa2f-21a3-4333-955f-67c0ac988cc2/6B3AFC74ACA841B24CFB94DB9044C84EDE6AFF31C71718B023D413DAED09A68E.jpeg"/></author><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb><id>https://pleroma.soykaf.com/activities/579e4224-b2ab-4ffa-8bbe-f7197a0a38d1</id><title>lain repeated a notice</title><content type="html">RT In just seven days, I can make you a man!&lt;br&gt; -- The Rocky Horror Picture Show</content><published>2017-05-05T08:38:03.385590</published><updated>2017-05-05T08:38:03.385598</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/e8673466-9642-4c9e-8781-f0f69d6b15ae</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/e8673466-9642-4c9e-8781-f0f69d6b15ae" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/579e4224-b2ab-4ffa-8bbe-f7197a0a38d1"/><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/53dd40f4-3069-45a1-863b-94a9b317093d</id><title>New note by fortune</title><content type="html">In just seven days, I can make you a man!&lt;br&gt; -- The Rocky Horror Picture Show</content><published>2017-05-05T02:10:02.930802</published><updated>2017-05-05T08:38:03.423539</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/e8673466-9642-4c9e-8781-f0f69d6b15ae</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/e8673466-9642-4c9e-8781-f0f69d6b15ae" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/53dd40f4-3069-45a1-863b-94a9b317093d" rel="self"/><author><id>https://pleroma.soykaf.com/users/fortune</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://pleroma.soykaf.com/users/fortune</uri><poco:preferredUsername>fortune</poco:preferredUsername><poco:displayName>fortune</poco:displayName><poco:note>The trusty unix fortune file</poco:note><name>fortune</name><link rel="avatar" href="https://pleroma.soykaf.com/media/07ed0371-2817-4d80-97e1-255ca632fac6/66BA0B957C5E18404D405029B6C2B01FF1A306FB6EEF3E1D1F4C30DEBB1156D7.jpeg"/></author><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></activity:object><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/fortune"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/2bc86888-a256-4771-bb53-903f375804f9</id><title>New note by lain</title><content type="html">RTs federating into pleroma now.</content><published>2017-05-04T18:18:50.276470</published><updated>2017-05-04T18:18:50.276476</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/b7ae9350-f317-48aa-8058-2668091bb280</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/b7ae9350-f317-48aa-8058-2668091bb280" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/2bc86888-a256-4771-bb53-903f375804f9" rel="self"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/902b1f50-f295-4189-8c15-9c880919e121</id><title>New favorite by lain</title><content type="html">lain favorited something</content><published>2017-05-04T08:03:01.308890</published><updated>2017-05-04T08:03:01.308927</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:gs.smuglo.li,2017-05-03:noticeId=2164642:objectType=comment</id></activity:object><ostatus:conversation>https://pleroma.soykaf.com/contexts/9419f742-aaba-4eb5-89a2-8b599e8bf43c</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/9419f742-aaba-4eb5-89a2-8b599e8bf43c" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/902b1f50-f295-4189-8c15-9c880919e121"/><thr:in-reply-to ref="tag:gs.smuglo.li,2017-05-03:noticeId=2164642:objectType=comment"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/2"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/4e396e66-b063-454c-92c6-583506a9a2de</id><title>New note by lain</title><content type="html">Classic.&lt;br&gt;&lt;a href='https://pleroma.soykaf.com/media/adc36781-9765-4d9a-b57c-99b7a99108b2/mikodaemonstop.jpg'&gt;https://pleroma.soykaf.com/media/adc36781-9765-4d9a-b57c-99b7a99108b2/mikodaemonstop.jpg&lt;/a&gt;</content><published>2017-05-04T07:59:45.180619</published><updated>2017-05-04T07:59:45.180628</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/6afd9659-41e6-406d-ae97-43b880722861</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/6afd9659-41e6-406d-ae97-43b880722861" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/4e396e66-b063-454c-92c6-583506a9a2de" rel="self"/><link rel="enclosure" href="https://pleroma.soykaf.com/media/adc36781-9765-4d9a-b57c-99b7a99108b2/mikodaemonstop.jpg" type="image/jpeg"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/85d183e9-c935-4655-a1e6-8d69a4108235</id><title>New note by lain</title><content type="html">ん?&lt;br&gt;&lt;a href='https://pleroma.soykaf.com/media/ab144c6d-a38c-4d35-a60b-9a998becc094/n.gif'&gt;https://pleroma.soykaf.com/media/ab144c6d-a38c-4d35-a60b-9a998becc094/n.gif&lt;/a&gt;</content><published>2017-05-04T07:58:08.810716</published><updated>2017-05-04T07:58:08.810726</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/2e1aa616-86ce-4b50-9c81-63045a972156</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/2e1aa616-86ce-4b50-9c81-63045a972156" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/85d183e9-c935-4655-a1e6-8d69a4108235" rel="self"/><link rel="enclosure" href="https://pleroma.soykaf.com/media/ab144c6d-a38c-4d35-a60b-9a998becc094/n.gif" type="image/gif"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/7c5c45bb-e4d9-4f72-b4c6-0314afbd3553</id><title>New note by lain</title><content type="html">yeah.</content><published>2017-05-04T07:55:17.335290</published><updated>2017-05-04T07:55:17.335299</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/702c06cf-56ff-4a2f-bf5a-150bc00bb168</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/702c06cf-56ff-4a2f-bf5a-150bc00bb168" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/7c5c45bb-e4d9-4f72-b4c6-0314afbd3553" rel="self"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/f33f5f54-1c1d-4462-b9ed-229bb635dfd8</id><title>New note by lain</title><content type="html">yeah.</content><published>2017-05-04T07:49:24.931484</published><updated>2017-05-04T07:49:24.931492</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/c4932e7a-00cb-431a-b4ec-7404cb9daf65</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/c4932e7a-00cb-431a-b4ec-7404cb9daf65" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/f33f5f54-1c1d-4462-b9ed-229bb635dfd8" rel="self"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/0709bc79-7ac5-4983-b6d0-2205bf5ceba3</id><title>New favorite by lain</title><content type="html">lain favorited something</content><published>2017-05-03T20:08:11.294579</published><updated>2017-05-03T20:08:11.294587</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:pawoo.net,2017-05-03:objectId=7967690:objectType=Status</id></activity:object><ostatus:conversation>https://pleroma.soykaf.com/contexts/07a4b34d-6255-4bb2-8c73-c295a09ac952</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/07a4b34d-6255-4bb2-8c73-c295a09ac952" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/0709bc79-7ac5-4983-b6d0-2205bf5ceba3"/><thr:in-reply-to ref="tag:pawoo.net,2017-05-03:objectId=7967690:objectType=Status"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pawoo.net/users/God_Emperor_of_Dune"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/72c0288e-62d8-43d9-b3d8-1a9d78be8375</id><title>New note by lain</title><content type="html">&lt;a href='https://pawoo.net/users/God_Emperor_of_Dune'&gt;@God_Emperor_of_Dune@pawoo.net&lt;/a&gt; no man, just some fun domination play among buddies, nothing homo about it.</content><published>2017-05-03T20:01:00.998314</published><updated>2017-05-03T20:01:00.998322</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/07a4b34d-6255-4bb2-8c73-c295a09ac952</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/07a4b34d-6255-4bb2-8c73-c295a09ac952" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/72c0288e-62d8-43d9-b3d8-1a9d78be8375" rel="self"/><thr:in-reply-to ref="tag:pawoo.net,2017-05-03:objectId=7966029:objectType=Status"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pawoo.net/users/God_Emperor_of_Dune"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/d846409e-cf2a-4b68-a149-d5de34a91b0d</id><title>New note by lain</title><content type="html">&lt;a href='https://social.heldscal.la/user/24974'&gt;@dtluna@social.heldscal.la&lt;/a&gt; btfo.&lt;br&gt;&lt;a href='https://pleroma.soykaf.com/media/fbe42e87-5574-4544-89ba-29ddf46227fa/pnc__picked_media_1889ce61-4961-4fea-8a14-04fe6783ebf6.jpg'&gt;https://pleroma.soykaf.com/media/fbe42e87-5574-4544-89ba-29ddf46227fa/pnc__picked_media_1889ce61-4961-4fea-8a14-04fe6783ebf6.jpg&lt;/a&gt;</content><published>2017-05-03T20:00:15.860995</published><updated>2017-05-03T20:00:15.861002</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/0e88f35e-1a38-4181-bef9-5cbb0d943c63</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/0e88f35e-1a38-4181-bef9-5cbb0d943c63" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/d846409e-cf2a-4b68-a149-d5de34a91b0d" rel="self"/><link rel="enclosure" href="https://pleroma.soykaf.com/media/fbe42e87-5574-4544-89ba-29ddf46227fa/pnc__picked_media_1889ce61-4961-4fea-8a14-04fe6783ebf6.jpg" type="image/jpeg"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/24974"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/9075265f-f3b2-40e8-809f-10714f05a1fd</id><title>New note by lain</title><content type="html">#nohomo &lt;br&gt;&lt;a href='https://pleroma.soykaf.com/media/5cc5ad91-d637-4c45-a691-5ea778dc1bb3/pnc__picked_media_f62dc9ae-ea23-4fe6-bf85-cb75a129ab34.jpg'&gt;https://pleroma.soykaf.com/media/5cc5ad91-d637-4c45-a691-5ea778dc1bb3/pnc__picked_media_f62dc9ae-ea23-4fe6-bf85-cb75a129ab34.jpg&lt;/a&gt;</content><published>2017-05-03T19:50:38.589106</published><updated>2017-05-03T19:50:38.589113</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/07a4b34d-6255-4bb2-8c73-c295a09ac952</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/07a4b34d-6255-4bb2-8c73-c295a09ac952" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/9075265f-f3b2-40e8-809f-10714f05a1fd" rel="self"/><link rel="enclosure" href="https://pleroma.soykaf.com/media/5cc5ad91-d637-4c45-a691-5ea778dc1bb3/pnc__picked_media_f62dc9ae-ea23-4fe6-bf85-cb75a129ab34.jpg" type="image/jpeg"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/7924e992-0a95-40d9-8d17-7278c6c634c9</id><title>New favorite by lain</title><content type="html">lain favorited something</content><published>2017-05-03T18:32:59.273375</published><updated>2017-05-03T18:32:59.273382</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:gs.smuglo.li,2017-05-03:noticeId=2164774:objectType=comment</id></activity:object><ostatus:conversation>https://pleroma.soykaf.com/contexts/9419f742-aaba-4eb5-89a2-8b599e8bf43c</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/9419f742-aaba-4eb5-89a2-8b599e8bf43c" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/7924e992-0a95-40d9-8d17-7278c6c634c9"/><thr:in-reply-to ref="tag:gs.smuglo.li,2017-05-03:noticeId=2164774:objectType=comment"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/2"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/569571ba-f54c-41b0-bde4-0fede54599f0</id><title>New note by lain</title><content type="html">&lt;a href='https://gs.smuglo.li/user/2'&gt;@nepfag@gs.smuglo.li&lt;/a&gt;@gs.smuglo.li I'll do proper subfolders soon, for now it's one per attachment + thumbs etc.</content><published>2017-05-03T18:27:01.449949</published><updated>2017-05-03T18:27:01.449956</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/9419f742-aaba-4eb5-89a2-8b599e8bf43c</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/9419f742-aaba-4eb5-89a2-8b599e8bf43c" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/569571ba-f54c-41b0-bde4-0fede54599f0" rel="self"/><thr:in-reply-to ref="tag:gs.smuglo.li,2017-05-03:noticeId=2164642:objectType=comment"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/2"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb><id>https://pleroma.soykaf.com/activities/b6cc5d7c-0785-4785-a689-f1b05dc9b24d</id><title>lain repeated a notice</title><content type="html">RT &lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Hey now!&lt;/p&gt;</content><published>2017-05-03T18:13:48.891061</published><updated>2017-05-03T18:13:48.891069</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/ec6fdd27-0ec1-4672-8408-5a8e5a9c094b</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/ec6fdd27-0ec1-4672-8408-5a8e5a9c094b" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/b6cc5d7c-0785-4785-a689-f1b05dc9b24d"/><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>tag:mastodon.social,2017-05-01:objectId=4836142:objectType=Status</id><title>New note by lambadalambda@mastodon.social</title><content type="html">&lt;p&gt;&lt;span class="h-card"&gt;&lt;a href="https://pleroma.soykaf.com/users/lain" class="u-url mention"&gt;@&lt;span&gt;lain&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; Hey now!&lt;/p&gt;</content><published>2017-05-01T18:38:49.365391</published><updated>2017-05-03T18:13:48.934745</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/ec6fdd27-0ec1-4672-8408-5a8e5a9c094b</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/ec6fdd27-0ec1-4672-8408-5a8e5a9c094b" rel="ostatus:conversation"/><link type="application/atom+xml" href="tag:mastodon.social,2017-05-01:objectId=4836142:objectType=Status" rel="self"/><thr:in-reply-to ref="https://pleroma.soykaf.com/objects/ffae4bea-00a3-4cef-8076-4ee4d448cb46"/><author><id>https://mastodon.social/users/lambadalambda</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://mastodon.social/users/lambadalambda</uri><poco:preferredUsername>lambadalambda@mastodon.social</poco:preferredUsername><poco:displayName>Critical Value</poco:displayName><poco:note>nil</poco:note><name>lambadalambda@mastodon.social</name><link rel="avatar" href="https://files.mastodon.social/accounts/avatars/000/000/264/original/1429214160519.gif"/></author><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/></activity:object><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/lambadalambda"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb><id>https://pleroma.soykaf.com/activities/3c09eb31-4ba8-4ff5-b4fa-8f6f74d58bf0</id><title>lain repeated a notice</title><content type="html">RT Haha, salmons from mastodon didn't work because it's not implementing conversation id...</content><published>2017-05-03T18:13:15.148041</published><updated>2017-05-03T18:13:15.148049</updated><ostatus:conversation>tag:social.heldscal.la,2017-05-01:objectType=thread:nonce=86cda6c734401d80</ostatus:conversation><link href="tag:social.heldscal.la,2017-05-01:objectType=thread:nonce=86cda6c734401d80" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/3c09eb31-4ba8-4ff5-b4fa-8f6f74d58bf0"/><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>tag:social.heldscal.la,2017-05-01:noticeId=2000425:objectType=note</id><title>New note by lambadalambda@social.heldscal.la</title><content type="html">Haha, salmons from mastodon didn't work because it's not implementing conversation id...</content><published>2017-05-01T18:39:36.216377</published><updated>2017-05-03T18:13:15.171143</updated><ostatus:conversation>tag:social.heldscal.la,2017-05-01:objectType=thread:nonce=86cda6c734401d80</ostatus:conversation><link href="tag:social.heldscal.la,2017-05-01:objectType=thread:nonce=86cda6c734401d80" rel="ostatus:conversation"/><link type="application/atom+xml" href="tag:social.heldscal.la,2017-05-01:noticeId=2000425:objectType=note" rel="self"/><author><id>https://social.heldscal.la/user/23211</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://social.heldscal.la/user/23211</uri><poco:preferredUsername>lambadalambda@social.heldscal.la</poco:preferredUsername><poco:displayName>Constance Variable</poco:displayName><poco:note>nil</poco:note><name>lambadalambda@social.heldscal.la</name><link rel="avatar" href="https://social.heldscal.la/avatar/23211-original-20170416114255.jpeg"/></author><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></activity:object><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/23211"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/b8fc83d5-d7c0-4b5f-8976-0317b51935ea</id><title>New note by lain</title><content type="html">.&lt;br&gt;&lt;a href='https://pleroma.soykaf.com/media/563008a7-9a60-47ac-a263-22835729adf6/1492530528735.png'&gt;https://pleroma.soykaf.com/media/563008a7-9a60-47ac-a263-22835729adf6/1492530528735.png&lt;/a&gt;</content><published>2017-05-03T18:12:50.745241</published><updated>2017-05-03T18:12:50.745249</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/9419f742-aaba-4eb5-89a2-8b599e8bf43c</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/9419f742-aaba-4eb5-89a2-8b599e8bf43c" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/b8fc83d5-d7c0-4b5f-8976-0317b51935ea" rel="self"/><link rel="enclosure" href="https://pleroma.soykaf.com/media/563008a7-9a60-47ac-a263-22835729adf6/1492530528735.png" type="image/png"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb><id>https://pleroma.soykaf.com/activities/ac93ecef-cde0-48e8-ae4b-19e3b94dbe30</id><title>lain repeated a notice</title><content type="html">RT Awright, which one of you hid my PENIS ENVY?</content><published>2017-05-03T18:08:49.231001</published><updated>2017-05-03T18:08:49.235354</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/a9132cf8-6afa-4dd8-8b29-7b6fcab623b8</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/a9132cf8-6afa-4dd8-8b29-7b6fcab623b8" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/ac93ecef-cde0-48e8-ae4b-19e3b94dbe30"/><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/04e15c66-4936-4930-a134-32841f088bcf</id><title>New note by fortune</title><content type="html">Awright, which one of you hid my PENIS ENVY?</content><published>2017-05-01T19:40:03.169996</published><updated>2017-05-03T18:08:49.285347</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/a9132cf8-6afa-4dd8-8b29-7b6fcab623b8</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/a9132cf8-6afa-4dd8-8b29-7b6fcab623b8" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/04e15c66-4936-4930-a134-32841f088bcf" rel="self"/><author><id>https://pleroma.soykaf.com/users/fortune</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://pleroma.soykaf.com/users/fortune</uri><poco:preferredUsername>fortune</poco:preferredUsername><poco:displayName>fortune</poco:displayName><poco:note>The trusty unix fortune file</poco:note><name>fortune</name><link rel="avatar" href="https://pleroma.soykaf.com/media/07ed0371-2817-4d80-97e1-255ca632fac6/66BA0B957C5E18404D405029B6C2B01FF1A306FB6EEF3E1D1F4C30DEBB1156D7.jpeg"/></author><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></activity:object><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/fortune"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb><id>https://pleroma.soykaf.com/activities/54b10fa9-d602-4a0f-b659-e6d3f7bc8c4c</id><title>lain repeated a notice</title><content type="html">RT He is a man capable of turning any colour into grey.&lt;br&gt; -- John LeCarre</content><published>2017-05-03T17:44:47.578984</published><updated>2017-05-03T17:44:47.578996</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/8aebc8e5-5352-4047-8b74-4098a5830cca</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/8aebc8e5-5352-4047-8b74-4098a5830cca" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/54b10fa9-d602-4a0f-b659-e6d3f7bc8c4c"/><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/70ded299-184d-49cd-af17-23c0950536aa</id><title>New note by fortune</title><content type="html">He is a man capable of turning any colour into grey.&lt;br&gt; -- John LeCarre</content><published>2017-05-02T08:40:03.419465</published><updated>2017-05-03T17:44:47.646192</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/8aebc8e5-5352-4047-8b74-4098a5830cca</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/8aebc8e5-5352-4047-8b74-4098a5830cca" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/70ded299-184d-49cd-af17-23c0950536aa" rel="self"/><author><id>https://pleroma.soykaf.com/users/fortune</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://pleroma.soykaf.com/users/fortune</uri><poco:preferredUsername>fortune</poco:preferredUsername><poco:displayName>fortune</poco:displayName><poco:note>The trusty unix fortune file</poco:note><name>fortune</name><link rel="avatar" href="https://pleroma.soykaf.com/media/07ed0371-2817-4d80-97e1-255ca632fac6/66BA0B957C5E18404D405029B6C2B01FF1A306FB6EEF3E1D1F4C30DEBB1156D7.jpeg"/></author><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></activity:object><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/fortune"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb><id>https://pleroma.soykaf.com/activities/eff9fe49-8fc9-48e6-a1a0-921aa25c8118</id><title>lain repeated a notice</title><content type="html">RT The real trouble with women is that they have *all* the pussy.</content><published>2017-05-03T17:30:22.596037</published><updated>2017-05-03T17:30:22.596048</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/8c88c9df-4e40-4f54-b15f-c21848d1a8e2</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/8c88c9df-4e40-4f54-b15f-c21848d1a8e2" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/eff9fe49-8fc9-48e6-a1a0-921aa25c8118"/><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/0b9b008d-49eb-48a9-a18d-172ce7d01ea2</id><title>New note by fortune</title><content type="html">The real trouble with women is that they have *all* the pussy.</content><published>2017-05-02T12:10:03.603086</published><updated>2017-05-03T17:30:22.683141</updated><ostatus:conversation>https://pleroma.soykaf.com/contexts/8c88c9df-4e40-4f54-b15f-c21848d1a8e2</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/8c88c9df-4e40-4f54-b15f-c21848d1a8e2" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/0b9b008d-49eb-48a9-a18d-172ce7d01ea2" rel="self"/><author><id>https://pleroma.soykaf.com/users/fortune</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://pleroma.soykaf.com/users/fortune</uri><poco:preferredUsername>fortune</poco:preferredUsername><poco:displayName>fortune</poco:displayName><poco:note>The trusty unix fortune file</poco:note><name>fortune</name><link rel="avatar" href="https://pleroma.soykaf.com/media/07ed0371-2817-4d80-97e1-255ca632fac6/66BA0B957C5E18404D405029B6C2B01FF1A306FB6EEF3E1D1F4C30DEBB1156D7.jpeg"/></author><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></activity:object><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/fortune"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/5d90bb26-ce23-4a5b-8dbd-651011780007</id><title>New favorite by lain</title><content type="html">lain favorited something</content><published>2017-05-03T17:28:20.967926</published><updated>2017-05-03T17:28:20.967935</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:mastodon.social,2017-05-03:objectId=4952899:objectType=Status</id></activity:object><ostatus:conversation>https://pleroma.soykaf.com/contexts/42701ab4-964a-441a-a372-f51bd183e441</ostatus:conversation><link href="https://pleroma.soykaf.com/contexts/42701ab4-964a-441a-a372-f51bd183e441" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/5d90bb26-ce23-4a5b-8dbd-651011780007"/><thr:in-reply-to ref="tag:mastodon.social,2017-05-03:objectId=4952899:objectType=Status"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/lambadalambda"/></entry></feed> -\ No newline at end of file diff --git a/test/fixtures/tesla_mock/https___shitposter.club_api_statuses_show_2827873.atom.xml b/test/fixtures/tesla_mock/https___shitposter.club_api_statuses_show_2827873.atom.xml @@ -1,54 +0,0 @@ -<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> diff --git a/test/fixtures/tesla_mock/https___shitposter.club_api_statuses_user_timeline_1.atom.xml b/test/fixtures/tesla_mock/https___shitposter.club_api_statuses_user_timeline_1.atom.xml @@ -1,454 +0,0 @@ -<?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-beta4">GNU social</generator> - <id>https://shitposter.club/api/statuses/user_timeline/1.atom</id> - <title>moonman timeline</title> - <subtitle>Updates from moonman on Shitposter Club!</subtitle> - <logo>https://shitposter.club/avatar/1-96-20170503024316.jpeg</logo> - <updated>2017-05-05T13:24:09+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> - <link href="https://shitposter.club/moonman" rel="alternate" type="text/html"/> - <link href="https://shitposter.club/main/sup" rel="http://api.friendfeed.com/2008/03#sup" type="application/json"/> - <link href="https://shitposter.club/api/statuses/user_timeline/1.atom?max_id=2828044" rel="next" type="application/atom+xml"/> - <link href="https://shitposter.club/main/push/hub" rel="hub"/> - <link href="https://shitposter.club/main/salmon/user/1" rel="salmon"/> - <link href="https://shitposter.club/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-replies"/> - <link href="https://shitposter.club/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-mention"/> - <link href="https://shitposter.club/api/statuses/user_timeline/1.atom" rel="self" type="application/atom+xml"/> -<entry> - <id>tag:shitposter.club,2017-05-05:subscription:1:person:23190:2017-05-05T11:43:58+00:00</id> - <title>Generic Enemy (moonman)'s status on Friday, 05-May-2017 11:43:58 UTC</title> - <content type="html">&lt;a href=&quot;https://shitposter.club/moonman&quot;&gt;Generic Enemy&lt;/a&gt; started following &lt;a href=&quot;https://noagendasocial.com/@Ma5on&quot;&gt;Mason&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2829381"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-05-05T11:43:58+00:00</published> - <updated>2017-05-05T11:43:58+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://noagendasocial.com/users/Ma5on</id> - <title>Mason</title> - <link rel="alternate" type="text/html" href="https://noagendasocial.com/@Ma5on"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://shitposter.club/avatar/23190-original-20170505114356.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://shitposter.club/avatar/23190-96-20170505114358.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://shitposter.club/avatar/23190-48-20170505114358.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://shitposter.club/avatar/23190-24-20170505114358.jpeg"/> - <poco:preferredUsername>ma5on</poco:preferredUsername> - <poco:displayName>Mason</poco:displayName> - </activity:object> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1391451"/> - <ostatus:conversation href="https://shitposter.club/conversation/1391451" local_id="1391451" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=abffa9c14a054d3b">tag:shitposter.club,2017-05-05:objectType=thread:nonce=abffa9c14a054d3b</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://shitposter.club/api/statuses/show/2829381.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2829381.atom"/> - <statusnet:notice_info local_id="2829381" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:shitposter.club,2017-05-05:subscription:1:person:14357:2017-05-05T10:29:03+00:00</id> - <title>Generic Enemy (moonman)'s status on Friday, 05-May-2017 10:29:03 UTC</title> - <content type="html">&lt;a href=&quot;https://shitposter.club/moonman&quot;&gt;Generic Enemy&lt;/a&gt; started following &lt;a href=&quot;https://mastodon.cloud/@ohyran&quot;&gt;Jens Reuterberg&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828682"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-05-05T10:29:03+00:00</published> - <updated>2017-05-05T10:29:03+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://mastodon.cloud/users/ohyran</id> - <title>Jens Reuterberg</title> - <summary>RPG-nerd, illustrator, Open Source enthusiast, KDE dude, designer and gay lefty. Might be a cliché - but we will soon find out!</summary> - <link rel="alternate" type="text/html" href="https://mastodon.cloud/@ohyran"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://shitposter.club/avatar/14357-original-20170505110123.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://shitposter.club/avatar/14357-96-20170505110757.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://shitposter.club/avatar/14357-48-20170505110757.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://shitposter.club/avatar/14357-24-20170505110757.jpeg"/> - <poco:preferredUsername>ohyran</poco:preferredUsername> - <poco:displayName>Jens Reuterberg</poco:displayName> - <poco:note>RPG-nerd, illustrator, Open Source enthusiast, KDE dude, designer and gay lefty. Might be a cliché - but we will soon find out!</poco:note> - </activity:object> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390971"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390971" local_id="1390971" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=937151d4825a85bf">tag:shitposter.club,2017-05-05:objectType=thread:nonce=937151d4825a85bf</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://shitposter.club/api/statuses/show/2828682.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828682.atom"/> - <statusnet:notice_info local_id="2828682" source="activity"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828637:objectType=note</id> - <title>New note by moonman</title> - <content type="html">basicall i would just rather have ppl say &amp;quot;i like x and y&amp;quot; than &amp;quot;i'm a nerd&amp;quot; the term can be retired.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828637"/> - <status_net notice_id="2828637"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:24:54+00:00</published> - <updated>2017-05-05T10:24:54+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390949"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390949" local_id="1390949" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=65992b0b9b5e6931">tag:shitposter.club,2017-05-05:objectType=thread:nonce=65992b0b9b5e6931</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://shitposter.club/api/statuses/show/2828637.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828637.atom"/> - <statusnet:notice_info local_id="2828637" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828579:objectType=comment</id> - <title>New comment by moonman</title> - <content type="html">@&lt;a href=&quot;https://gs.smuglo.li/user/35497&quot; class=&quot;h-card mention&quot; title=&quot;Bokuro Bokusawa&quot;&gt;boco&lt;/a&gt; to be honest i've turned right around and been cruel to other people, i said i'd never do it but it happens again eventually.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828579"/> - <status_net notice_id="2828579"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:20:33+00:00</published> - <updated>2017-05-05T10:20:33+00:00</updated> - <thr:in-reply-to ref="tag:gs.smuglo.li,2017-05-05:noticeId=2189031:objectType=comment" href="https://gs.smuglo.li/notice/2189031"></thr:in-reply-to> - <link rel="related" href="https://gs.smuglo.li/notice/2189031"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390862"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390862" local_id="1390862" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=c997fc73d7f8a8f0">tag:shitposter.club,2017-05-05:objectType=thread:nonce=c997fc73d7f8a8f0</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/35497"/> - <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://shitposter.club/api/statuses/show/2828579.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828579.atom"/> - <statusnet:notice_info local_id="2828579" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828554:objectType=comment</id> - <title>New comment by moonman</title> - <content type="html">@&lt;a href=&quot;https://mastodon.cloud/users/ohyran&quot; class=&quot;h-card mention&quot; title=&quot;Jens Reuterberg&quot;&gt;ohyran&lt;/a&gt; i won't ever get over bullying but i agree otherwise. i don't go to comic shops too often these days but i got dragged to one last year and the sheer diversity of people enjoying comics now compared to years ago was striking and it pleased me. and i noticed a couple years ago because of youtube i find things i truly enjoy watching, like in-depth videos about electronic parts, didn't exist 20 years ago. it's pretty great.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828554"/> - <status_net notice_id="2828554"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:18:10+00:00</published> - <updated>2017-05-05T10:18:10+00:00</updated> - <thr:in-reply-to ref="tag:mastodon.cloud,2017-05-05:objectId=6334570:objectType=Status" href="https://mastodon.cloud/users/ohyran/updates/595969"></thr:in-reply-to> - <link rel="related" href="https://mastodon.cloud/users/ohyran/updates/595969"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390752"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390752" local_id="1390752" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767">tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.cloud/users/ohyran"/> - <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://shitposter.club/api/statuses/show/2828554.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828554.atom"/> - <statusnet:notice_info local_id="2828554" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <id>tag:shitposter.club,2017-05-05:fave:1:comment:2828502:2017-05-05T10:12:52+00:00</id> - <title>Favorite</title> - <content type="html">moonman favorited something by ohyran: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://shitposter.club/moonman&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;moonman&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; fair enough - that distinction makes it clearer...&lt;/p&gt;&lt;p&gt;On the other hand - those of us who did &quot;pay the price&quot; of being nerdy little kids in the 80's and 90's should strive to get past it anyway (mental health wise not &quot;just get over it&quot;) and see the &quot;nerd culture&quot; thing as a blessing of sorts. We are in the optimal spot to do it. (not saying that that is something easy btw just that NOW is the best of time to start talking about it)&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828506"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T10:12:52+00:00</published> - <updated>2017-05-05T10:12:52+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:mastodon.cloud,2017-05-05:objectId=6334570:objectType=Status</id> - <title>New comment by ohyran</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://shitposter.club/moonman&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;moonman&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; fair enough - that distinction makes it clearer...&lt;/p&gt;&lt;p&gt;On the other hand - those of us who did &quot;pay the price&quot; of being nerdy little kids in the 80's and 90's should strive to get past it anyway (mental health wise not &quot;just get over it&quot;) and see the &quot;nerd culture&quot; thing as a blessing of sorts. We are in the optimal spot to do it. (not saying that that is something easy btw just that NOW is the best of time to start talking about it)&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mastodon.cloud/users/ohyran/updates/595969"/> - <status_net notice_id="2828502"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:mastodon.cloud,2017-05-05:objectId=6334570:objectType=Status" href="https://mastodon.cloud/users/ohyran/updates/595969"></thr:in-reply-to> - <link rel="related" href="https://mastodon.cloud/users/ohyran/updates/595969"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390752"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390752" local_id="1390752" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767">tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767</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://shitposter.club/api/statuses/show/2828506.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828506.atom"/> - <statusnet:notice_info local_id="2828506" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828496:objectType=note</id> - <title>New note by moonman</title> - <content type="html">things are better now, a lot less kids in america get beaten up and called a fag. still too many.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828496"/> - <status_net notice_id="2828496"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:11:31+00:00</published> - <updated>2017-05-05T10:11:31+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390862"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390862" local_id="1390862" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=c997fc73d7f8a8f0">tag:shitposter.club,2017-05-05:objectType=thread:nonce=c997fc73d7f8a8f0</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://shitposter.club/api/statuses/show/2828496.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828496.atom"/> - <statusnet:notice_info local_id="2828496" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828457:objectType=comment</id> - <title>New comment by moonman</title> - <content type="html">@&lt;a href=&quot;https://shitposter.club/user/21787&quot; class=&quot;h-card mention&quot; title=&quot;Yukari&quot;&gt;cutscenes&lt;/a&gt; @&lt;a href=&quot;https://gs.smuglo.li/user/28250&quot; class=&quot;h-card mention&quot; title=&quot;Bricky&quot;&gt;thatbrickster&lt;/a&gt; @&lt;a href=&quot;https://gs.smuglo.li/user/35497&quot; class=&quot;h-card mention&quot; title=&quot;Bokuro Bokusawa&quot;&gt;boco&lt;/a&gt; i never understood this because nerds had pocket protectors, which was a draftsman engineer thing and therefore smart, while geeks were people in carnivals who bit heads off small animals.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828457"/> - <status_net notice_id="2828457"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:07:57+00:00</published> - <updated>2017-05-05T10:07:57+00:00</updated> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2828427:objectType=comment" href="https://shitposter.club/notice/2828427"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2828427"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390752"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390752" local_id="1390752" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767">tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/28250"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/35497"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/21787"/> - <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://shitposter.club/api/statuses/show/2828457.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828457.atom"/> - <statusnet:notice_info local_id="2828457" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828435:objectType=comment</id> - <title>New comment by moonman</title> - <content type="html">@&lt;a href=&quot;https://mastodon.cloud/users/ohyran&quot; class=&quot;h-card mention&quot; title=&quot;Jens Reuterberg&quot;&gt;ohyran&lt;/a&gt; since i didn't specify i'm talking about people subjected to physical and psychological abuse and not people that are just mad that more people like comic books now.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828435"/> - <status_net notice_id="2828435"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:05:07+00:00</published> - <updated>2017-05-05T10:05:07+00:00</updated> - <thr:in-reply-to ref="tag:mastodon.cloud,2017-05-05:objectId=6331705:objectType=Status" href="https://mastodon.cloud/users/ohyran/updates/595757"></thr:in-reply-to> - <link rel="related" href="https://mastodon.cloud/users/ohyran/updates/595757"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390752"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390752" local_id="1390752" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767">tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.cloud/users/ohyran"/> - <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://shitposter.club/api/statuses/show/2828435.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828435.atom"/> - <statusnet:notice_info local_id="2828435" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828326:objectType=note</id> - <title>New note by moonman</title> - <content type="html">if you were a &amp;quot;nerd&amp;quot; before, like, 2001 you have permanent excuse to hate this kind of shit.   &lt;a href=&quot;https://shitposter.club/file/b79fa5644be0d6f22679136e67b7bf45c9c4a74a55c32dd2d0cf15de4ddd5be5.gif&quot; title=&quot;https://shitposter.club/file/b79fa5644be0d6f22679136e67b7bf45c9c4a74a55c32dd2d0cf15de4ddd5be5.gif&quot; class=&quot;attachment&quot; id=&quot;attachment-662105&quot; rel=&quot;nofollow external&quot;&gt;https://shitposter.club/attachment/662105&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828326"/> - <status_net notice_id="2828326"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:47:42+00:00</published> - <updated>2017-05-05T09:47:42+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390752"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390752" local_id="1390752" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767">tag:shitposter.club,2017-05-05:objectType=thread:nonce=efae3a23b6e05767</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" href="https://shitposter.club/file/b79fa5644be0d6f22679136e67b7bf45c9c4a74a55c32dd2d0cf15de4ddd5be5.gif" type="image/gif" length="1023884"/> - <link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828326.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828326.atom"/> - <statusnet:notice_info local_id="2828326" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828250:objectType=note</id> - <title>New note by moonman</title> - <content type="html">&lt;a href=&quot;https://shitposter.club/file/1283e2d4dd8f96b8eeb5d9a16b318e210868aa11386cf0d593891e4c75c9126e.gif&quot; title=&quot;https://shitposter.club/file/1283e2d4dd8f96b8eeb5d9a16b318e210868aa11386cf0d593891e4c75c9126e.gif&quot; class=&quot;attachment&quot; id=&quot;attachment-662098&quot; rel=&quot;nofollow external&quot;&gt;https://shitposter.club/attachment/662098&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828250"/> - <status_net notice_id="2828250"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:39:06+00:00</published> - <updated>2017-05-05T09:39:06+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390709"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390709" local_id="1390709" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=ea8ffae90546f0ab">tag:shitposter.club,2017-05-05:objectType=thread:nonce=ea8ffae90546f0ab</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" href="https://shitposter.club/file/1283e2d4dd8f96b8eeb5d9a16b318e210868aa11386cf0d593891e4c75c9126e.gif" type="image/gif" length="1020391"/> - <link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828250.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828250.atom"/> - <statusnet:notice_info local_id="2828250" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <id>tag:shitposter.club,2017-05-05:fave:1:comment:2828161:2017-05-05T09:28:19+00:00</id> - <title>Favorite</title> - <content type="html">moonman favorited something by kro: @&lt;a href=&quot;https://shitposter.club/user/1&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Generic Enemy&quot;&gt;moonman&lt;/a&gt; Till Brooklyn?</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828162"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T09:28:19+00:00</published> - <updated>2017-05-05T09:28:19+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:gs.smuglo.li,2017-05-05:noticeId=2188587:objectType=comment</id> - <title>New comment by kro</title> - <content type="html">@&lt;a href=&quot;https://shitposter.club/user/1&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Generic Enemy&quot;&gt;moonman&lt;/a&gt; Till Brooklyn?</content> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/notice/2188587"/> - <status_net notice_id="2828161"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:gs.smuglo.li,2017-05-05:noticeId=2188587:objectType=comment" href="https://gs.smuglo.li/notice/2188587"></thr:in-reply-to> - <link rel="related" href="https://gs.smuglo.li/notice/2188587"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390624"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390624" local_id="1390624" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=d7aa6b5b057ca555">tag:shitposter.club,2017-05-05:objectType=thread:nonce=d7aa6b5b057ca555</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://shitposter.club/api/statuses/show/2828162.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828162.atom"/> - <statusnet:notice_info local_id="2828162" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:shitposter.club,2017-05-05:fave:1:comment:2828125:2017-05-05T09:24:56+00:00</id> - <title>Favorite</title> - <content type="html">moonman favorited something by hardbass2k8: this has obviously interesting implications in various places, for example:&lt;br /&gt; the nationalism of the nazis might not have been real, who would have thought?&lt;br /&gt; socialism is usually promoted to implementation by real douchebags!&lt;br /&gt; your local social justice people might want diversity but they don't want you, m/19, white, why?&lt;br /&gt; amateur soccer club, they want to be the best in the amateur league but actually they just get drunk after training and are 50% overweight.&lt;br /&gt; This is because humans are not capable of telepathy, so if you join a group it doesn't magically align every little bit of your being with the declared group goals.&lt;br /&gt; &lt;br /&gt; Even though you see unmanned group beliefs flying around from time to time, generally groups are created from a bunch of people. they are not a container for people, they are the people inside them.&lt;br /&gt; &lt;br /&gt; so if you see a group that appears to be cool don't think of it as cool because its goals are cool but because its members are cool. if they aren't, tough cookies. don't be the retard and end up on the camp watchtower.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828136"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T09:24:56+00:00</published> - <updated>2017-05-05T09:24:56+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=2828125:objectType=comment</id> - <title>New comment by hardbass2k8</title> - <content type="html">this has obviously interesting implications in various places, for example:&lt;br /&gt; the nationalism of the nazis might not have been real, who would have thought?&lt;br /&gt; socialism is usually promoted to implementation by real douchebags!&lt;br /&gt; your local social justice people might want diversity but they don't want you, m/19, white, why?&lt;br /&gt; amateur soccer club, they want to be the best in the amateur league but actually they just get drunk after training and are 50% overweight.&lt;br /&gt; This is because humans are not capable of telepathy, so if you join a group it doesn't magically align every little bit of your being with the declared group goals.&lt;br /&gt; &lt;br /&gt; Even though you see unmanned group beliefs flying around from time to time, generally groups are created from a bunch of people. they are not a container for people, they are the people inside them.&lt;br /&gt; &lt;br /&gt; so if you see a group that appears to be cool don't think of it as cool because its goals are cool but because its members are cool. if they aren't, tough cookies. don't be the retard and end up on the camp watchtower.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828125"/> - <status_net notice_id="2828125"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2828125:objectType=comment" href="https://shitposter.club/notice/2828125"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2828125"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390589"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390589" local_id="1390589" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=51b227fe92f6babf">tag:shitposter.club,2017-05-05:objectType=thread:nonce=51b227fe92f6babf</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://shitposter.club/api/statuses/show/2828136.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828136.atom"/> - <statusnet:notice_info local_id="2828136" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828128:objectType=note</id> - <title>New note by moonman</title> - <content type="html">In a valid remake of They live, signs would say REBEL, and DON'T GET MARRIED AND HAVE KIDS</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828128"/> - <status_net notice_id="2828128"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:24:23+00:00</published> - <updated>2017-05-05T09:24:23+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390642"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390642" local_id="1390642" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=b74397fa766b82c9">tag:shitposter.club,2017-05-05:objectType=thread:nonce=b74397fa766b82c9</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://shitposter.club/api/statuses/show/2828128.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828128.atom"/> - <statusnet:notice_info local_id="2828128" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828104:objectType=note</id> - <title>New note by moonman</title> - <content type="html">&lt;a href=&quot;https://shitposter.club/file/4d34178bde99599f31a28928e1666fbd58448d8a22e94ed82222496e4a45cb07.gif&quot; title=&quot;https://shitposter.club/file/4d34178bde99599f31a28928e1666fbd58448d8a22e94ed82222496e4a45cb07.gif&quot; class=&quot;attachment&quot; id=&quot;attachment-662049&quot; rel=&quot;nofollow external&quot;&gt;https://shitposter.club/attachment/662049&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828104"/> - <status_net notice_id="2828104"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:21:01+00:00</published> - <updated>2017-05-05T09:21:01+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390624"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390624" local_id="1390624" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=d7aa6b5b057ca555">tag:shitposter.club,2017-05-05:objectType=thread:nonce=d7aa6b5b057ca555</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" href="https://shitposter.club/file/4d34178bde99599f31a28928e1666fbd58448d8a22e94ed82222496e4a45cb07.gif" type="image/gif" length="278366"/> - <link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828104.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828104.atom"/> - <statusnet:notice_info local_id="2828104" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828102:objectType=note</id> - <title>New note by moonman</title> - <content type="html">when ppl find out i haven't always been serious  &lt;a href=&quot;https://shitposter.club/file/5859fa95875342cc65dba0d852f726db158ce28198c326d5f13d9de7c0d2c449.gif&quot; title=&quot;https://shitposter.club/file/5859fa95875342cc65dba0d852f726db158ce28198c326d5f13d9de7c0d2c449.gif&quot; class=&quot;attachment&quot; id=&quot;attachment-662053&quot; rel=&quot;nofollow external&quot;&gt;https://shitposter.club/attachment/662053&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828102"/> - <status_net notice_id="2828102"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:20:45+00:00</published> - <updated>2017-05-05T09:20:45+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390622"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390622" local_id="1390622" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=0a025ac5a570b4ec">tag:shitposter.club,2017-05-05:objectType=thread:nonce=0a025ac5a570b4ec</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" href="https://shitposter.club/file/5859fa95875342cc65dba0d852f726db158ce28198c326d5f13d9de7c0d2c449.gif" type="image/gif" length="119239"/> - <link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828102.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828102.atom"/> - <statusnet:notice_info local_id="2828102" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828086: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; @&lt;a href=&quot;https://gs.smuglo.li/user/35497&quot; class=&quot;h-card mention&quot; title=&quot;Bokuro Bokusawa&quot;&gt;boco&lt;/a&gt; you are being too serious lol</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828086"/> - <status_net notice_id="2828086"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:17:19+00:00</published> - <updated>2017-05-05T09:17:19+00:00</updated> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2828082:objectType=comment" href="https://shitposter.club/notice/2828082"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2828082"/> - <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/person" href="https://gs.smuglo.li/user/35497"/> - <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://shitposter.club/api/statuses/show/2828086.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828086.atom"/> - <statusnet:notice_info local_id="2828086" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828085:objectType=note</id> - <title>New note by moonman</title> - <content type="html">shitposter dot club  &lt;a href=&quot;https://shitposter.club/file/9b084c7210b16abbf4d28594b924a07ef4a2a06f89d901a4c42fb1e243291263.gif&quot; title=&quot;https://shitposter.club/file/9b084c7210b16abbf4d28594b924a07ef4a2a06f89d901a4c42fb1e243291263.gif&quot; class=&quot;attachment&quot; id=&quot;attachment-662047&quot; rel=&quot;nofollow external&quot;&gt;https://shitposter.club/attachment/662047&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828085"/> - <status_net notice_id="2828085"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:16:50+00:00</published> - <updated>2017-05-05T09:16:50+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390613"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390613" local_id="1390613" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=d1ae088a1b91e5e5">tag:shitposter.club,2017-05-05:objectType=thread:nonce=d1ae088a1b91e5e5</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" href="https://shitposter.club/file/9b084c7210b16abbf4d28594b924a07ef4a2a06f89d901a4c42fb1e243291263.gif" type="image/gif" length="681847"/> - <link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828085.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828085.atom"/> - <statusnet:notice_info local_id="2828085" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828061:objectType=note</id> - <title>New note by moonman</title> - <content type="html">even when i lie i tell the truth, is that so hard to understand?</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828061"/> - <status_net notice_id="2828061"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:15:07+00:00</published> - <updated>2017-05-05T09:15:07+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390593"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390593" local_id="1390593" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=a516e4b8506b8ef5">tag:shitposter.club,2017-05-05:objectType=thread:nonce=a516e4b8506b8ef5</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://shitposter.club/api/statuses/show/2828061.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828061.atom"/> - <statusnet:notice_info local_id="2828061" source="Qvitter"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2828052:objectType=comment</id> - <title>New comment by moonman</title> - <content type="html">@&lt;a href=&quot;https://shitposter.club/user/9591&quot; class=&quot;h-card mention&quot; title=&quot;warum hei&amp;#xDF;en deutschl&amp;#xE4;nder deutschl&amp;#xE4;nder&quot;&gt;hardbass2k8&lt;/a&gt; history, anthropology.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2828052"/> - <status_net notice_id="2828052"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T09:14:22+00:00</published> - <updated>2017-05-05T09:14:22+00:00</updated> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2828048:objectType=comment" href="https://shitposter.club/notice/2828048"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2828048"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/1390564"/> - <ostatus:conversation href="https://shitposter.club/conversation/1390564" local_id="1390564" ref="tag:shitposter.club,2017-05-05:objectType=thread:nonce=fe4d7f35b13403ba">tag:shitposter.club,2017-05-05:objectType=thread:nonce=fe4d7f35b13403ba</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/9591"/> - <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://shitposter.club/api/statuses/show/2828052.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/2828052.atom"/> - <statusnet:notice_info local_id="2828052" source="Qvitter"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/tesla_mock/https___shitposter.club_notice_2827873.json b/test/fixtures/tesla_mock/https___shitposter.club_notice_2827873.json @@ -1 +0,0 @@ -{"@context":["https://www.w3.org/ns/activitystreams","https://shitposter.club/schemas/litepub-0.1.jsonld",{"@language":"und"}],"actor":"https://shitposter.club/users/moonman","attachment":[],"attributedTo":"https://shitposter.club/users/moonman","cc":["https://shitposter.club/users/moonman/followers"],"content":"@<a href=\"https://shitposter.club/users/9655\" class=\"h-card mention\" title=\"Solidarity for Pigs\">neimzr4luzerz</a> @<a href=\"https://gs.smuglo.li/user/2326\" class=\"h-card mention\" title=\"Dolus_McHonest\">dolus</a> 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","context":"tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26","conversation":"tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26","id":"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment","inReplyTo":"tag:shitposter.club,2017-05-05:noticeId=2827849:objectType=comment","inReplyToStatusId":2827849,"published":"2017-05-05T08:51:48Z","sensitive":false,"summary":null,"tag":[],"to":["https://www.w3.org/ns/activitystreams#Public"],"type":"Note"} -\ No newline at end of file diff --git a/test/fixtures/tesla_mock/https___social.heldscal.la_api_statuses_user_timeline_23211.atom.xml b/test/fixtures/tesla_mock/https___social.heldscal.la_api_statuses_user_timeline_23211.atom.xml @@ -1,591 +0,0 @@ -<?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-05T12:01:21+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/api/statuses/user_timeline/23211.atom?max_id=2060731" rel="next" type="application/atom+xml"/> - <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:2063249:2017-05-05T11:40:21+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by tatiana: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; they will start complaining about this, but won't come up with any solutions)&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2063306"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T11:40:21+00:00</published> - <updated>2017-05-05T11:40:21+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.weho.st,2017-05-05:objectId=172033:objectType=Status</id> - <title>New comment by tatiana</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; they will start complaining about this, but won't come up with any solutions)&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.weho.st/users/Tatiana/updates/2841"/> - <status_net notice_id="2063249"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:social.weho.st,2017-05-05:objectId=172033:objectType=Status" href="https://social.weho.st/users/Tatiana/updates/2841"></thr:in-reply-to> - <link rel="related" href="https://social.weho.st/users/Tatiana/updates/2841"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</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/2063306.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2063306.atom"/> - <statusnet:notice_info local_id="2063306" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2063041:2017-05-05T11:27:28+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by kat: @&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; if the admin reading mine would delete a few it would be really useful in prioritising. </content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2063148"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T11:27:28+00:00</published> - <updated>2017-05-05T11:27:28+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:quitter.se,2017-05-05:noticeId=11807959:objectType=comment</id> - <title>New comment by kat</title> - <content type="html">@&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; if the admin reading mine would delete a few it would be really useful in prioritising. </content> - <link rel="alternate" type="text/html" href="http://quitter.se/notice/11807959"/> - <status_net notice_id="2063041"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:quitter.se,2017-05-05:noticeId=11807959:objectType=comment" href="http://quitter.se/notice/11807959"></thr:in-reply-to> - <link rel="related" href="http://quitter.se/notice/11807959"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</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/2063148.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2063148.atom"/> - <statusnet:notice_info local_id="2063148" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:noticeId=2062924:objectType=note</id> - <title>lambadalambda repeated a notice by nielsk</title> - <content type="html">RT @nielsk @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; but there are soooo many, where should I start to read?</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2062924"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-05-05T11:09:37+00:00</published> - <updated>2017-05-05T11:09:37+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>tag:mastodon.social,2017-05-05:objectId=5024471:objectType=Status</id> - <title></title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; but there are soooo many, where should I start to read?&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/nielsk/updates/2256348"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T11:05:18+00:00</published> - <updated>2017-05-05T11:05:18+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://mastodon.social/users/nielsk</uri> - <name>nielsk</name> - <summary>Sysadmin by day and ehm… sysadmin by night. Besides that old video games, Japan, economics and some other stuff</summary> - <link rel="alternate" type="text/html" href="https://mastodon.social/@nielsk"/> - <link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://social.heldscal.la/avatar/29849-original-20170428120037.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/29849-96-20170428120041.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/29849-48-20170428120041.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/29849-24-20170429103753.jpeg"/> - <poco:preferredUsername>nielsk</poco:preferredUsername> - <poco:displayName>nielsk</poco:displayName> - <poco:note>Sysadmin by day and ehm… sysadmin by night. Besides that old video games, Japan, economics and some other stuff</poco:note> - <statusnet:profile_info local_id="29849"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:mastodon.social,2017-05-05:objectId=5024471:objectType=Status</id> - <title>New comment by nielsk</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; but there are soooo many, where should I start to read?&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/nielsk/updates/2256348"/> - <status_net notice_id="2062875"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:social.heldscal.la,2017-05-05:noticeId=2062583:objectType=note" href="https://social.heldscal.la/notice/2062583"></thr:in-reply-to> - <link rel="related" href="https://social.heldscal.la/notice/2062583"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.heldscal.la/user/23211"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>https://mastodon.social/users/nielsk.atom</id> - <title>nielsk</title> - <link rel="alternate" type="text/html" href="https://mastodon.social/@nielsk"/> - <link rel="self" type="application/atom+xml" href="https://mastodon.social/users/nielsk.atom"/> - <icon>https://social.heldscal.la/avatar/29849-96-20170428120041.jpeg</icon> - <updated>2017-05-05T11:06:32+00:00</updated> - </source> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</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/2062924.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2062924.atom"/> - <statusnet:notice_info local_id="2062924" source="api" repeat_of="2062875"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2062875:2017-05-05T11:09:27+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by nielsk: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; but there are soooo many, where should I start to read?&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2062923"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T11:09:27+00:00</published> - <updated>2017-05-05T11:09:27+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:mastodon.social,2017-05-05:objectId=5024471:objectType=Status</id> - <title>New comment by nielsk</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; but there are soooo many, where should I start to read?&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mastodon.social/users/nielsk/updates/2256348"/> - <status_net notice_id="2062875"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:mastodon.social,2017-05-05:objectId=5024471:objectType=Status" href="https://mastodon.social/users/nielsk/updates/2256348"></thr:in-reply-to> - <link rel="related" href="https://mastodon.social/users/nielsk/updates/2256348"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</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/2062923.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2062923.atom"/> - <statusnet:notice_info local_id="2062923" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2062863:2017-05-05T11:09:11+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by kasil: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; surely, google is not that evil !&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2062921"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T11:09:11+00:00</published> - <updated>2017-05-05T11:09:11+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:loutre.info,2017-05-05:objectId=23331:objectType=Status</id> - <title>New comment by kasil</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;lambadalambda&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; surely, google is not that evil !&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://loutre.info/users/Kasil/updates/159"/> - <status_net notice_id="2062863"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:loutre.info,2017-05-05:objectId=23331:objectType=Status" href="https://loutre.info/users/Kasil/updates/159"></thr:in-reply-to> - <link rel="related" href="https://loutre.info/users/Kasil/updates/159"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</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/2062921.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2062921.atom"/> - <statusnet:notice_info local_id="2062921" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-05-05:noticeId=2062767:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://sealion.club/user/4&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;dewoo &amp;#x274E;&quot;&gt;dwmatiz&lt;/a&gt; dunno, probably.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2062767"/> - <status_net notice_id="2062767"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:55:17+00:00</published> - <updated>2017-05-05T10:55:17+00:00</updated> - <thr:in-reply-to ref="tag:sealion.club,2017-05-05:noticeId=3183881:objectType=comment" href="https://sealion.club/notice/3183881"></thr:in-reply-to> - <link rel="related" href="https://sealion.club/notice/3183881"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://sealion.club/user/4"/> - <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/2062767.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2062767.atom"/> - <statusnet:notice_info local_id="2062767" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-05-05:noticeId=2062705:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://gs.smuglo.li/user/28250&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Bricky&quot;&gt;thatbrickster&lt;/a&gt; I do it, too.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2062705"/> - <status_net notice_id="2062705"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:48:12+00:00</published> - <updated>2017-05-05T10:48:12+00:00</updated> - <thr:in-reply-to ref="tag:gs.smuglo.li,2017-05-05:noticeId=2189353:objectType=comment" href="https://gs.smuglo.li/notice/2189353"></thr:in-reply-to> - <link rel="related" href="https://gs.smuglo.li/notice/2189353"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/28250"/> - <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/2062705.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2062705.atom"/> - <statusnet:notice_info local_id="2062705" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-05-05:noticeId=2062620:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://social.tchncs.de/users/israuor&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Israuor &amp;#x2642;&quot;&gt;israuor&lt;/a&gt; @&lt;a href=&quot;https://mastodon.gougere.fr/users/bortzmeyer&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;S. Bortzmeyer &amp;#x2705;&quot;&gt;bortzmeyer&lt;/a&gt; so, 99%. 100% for 'normal' people.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2062620"/> - <status_net notice_id="2062620"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:38:52+00:00</published> - <updated>2017-05-05T10:38:52+00:00</updated> - <thr:in-reply-to ref="tag:social.tchncs.de,2017-05-05:objectId=1667119:objectType=Status" href="https://social.tchncs.de/users/israuor/updates/74901"></thr:in-reply-to> - <link rel="related" href="https://social.tchncs.de/users/israuor/updates/74901"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.tchncs.de/users/israuor"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.gougere.fr/users/bortzmeyer"/> - <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/2062620.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2062620.atom"/> - <statusnet:notice_info local_id="2062620" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-05-05:noticeId=2062583:objectType=note</id> - <title>New note by lambadalambda</title> - <content type="html">I wonder what'll happen when people realize the admin at their mail hoster can read all their e-mails.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2062583"/> - <status_net notice_id="2062583"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T10:35:45+00:00</published> - <updated>2017-05-05T10:35:45+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062581"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062581" local_id="1062581" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=e95b99adc050e198</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/2062583.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2062583.atom"/> - <statusnet:notice_info local_id="2062583" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:subscription:23211:person:35708:2017-05-05T09:34:46+00:00</id> - <title>Constance Variable (lambadalambda@social.heldscal.la)'s status on Friday, 05-May-2017 09:34:46 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot;&gt;Constance Variable&lt;/a&gt; started following &lt;a href=&quot;https://mastodon.social/@milouse&quot;&gt;milouse&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2062053"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-05-05T09:34:46+00:00</published> - <updated>2017-05-05T09:34:46+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://mastodon.social/users/milouse</id> - <title>milouse</title> - <summary>#Scout leader #sgdf, interested in #openweb, #semanticweb, #privacy, #foss and #socialeconomy. 0xA714ECAC8C9CEE3D</summary> - <link rel="alternate" type="text/html" href="https://mastodon.social/@milouse"/> - <link rel="avatar" type="image/png" media:width="120" media:height="120" href="https://social.heldscal.la/avatar/35708-original-20170505105902.png"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/35708-96-20170505105911.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/35708-48-20170505105911.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/35708-24-20170505105938.png"/> - <poco:preferredUsername>milouse</poco:preferredUsername> - <poco:displayName>milouse</poco:displayName> - <poco:note>#Scout leader #sgdf, interested in #openweb, #semanticweb, #privacy, #foss and #socialeconomy. 0xA714ECAC8C9CEE3D</poco:note> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062248"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062248" local_id="1062248" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=26ca19a355bb6135">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=26ca19a355bb6135</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/2062053.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2062053.atom"/> - <statusnet:notice_info local_id="2062053" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:noticeId=2061871:objectType=note</id> - <title>lambadalambda repeated a notice by safebot</title> - <content type="html">RT @&lt;a href=&quot;https://gs.smuglo.li/user/25857&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;safebot&quot;&gt;safebot&lt;/a&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/tag/cheers&quot; rel=&quot;tag&quot;&gt;cheers&lt;/a&gt;&lt;/span&gt; &lt;a href=&quot;https://gs.smuglo.li/attachment/456444&quot; title=&quot;https://gs.smuglo.li/attachment/456444&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-432334&quot;&gt;https://gs.smuglo.li/attachment/456444&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061871"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-05-05T09:16:17+00:00</published> - <updated>2017-05-05T09:16:17+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>tag:gs.smuglo.li,2017-05-05:noticeId=2188073:objectType=note</id> - <title></title> - <content type="html">#&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://gs.smuglo.li/tag/cheers&quot; rel=&quot;tag&quot;&gt;cheers&lt;/a&gt;&lt;/span&gt; &lt;a href=&quot;https://gs.smuglo.li/file/5099e73c83da778cd032a721e96880f99a868b712be2975d08238547a5ba06c7.jpg&quot; title=&quot;https://gs.smuglo.li/file/5099e73c83da778cd032a721e96880f99a868b712be2975d08238547a5ba06c7.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/456444&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/notice/2188073"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T08:36:53+00:00</published> - <updated>2017-05-05T08:36:53+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://gs.smuglo.li/user/25857</uri> - <name>safebot</name> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/safebot"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/25719-original-20161215233234.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/25719-original-20161215233234.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/25719-48-20161215233239.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/25719-24-20161215235533.jpeg"/> - <poco:preferredUsername>safebot</poco:preferredUsername> - <poco:displayName>safebot</poco:displayName> - <statusnet:profile_info local_id="25719"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.smuglo.li,2017-05-05:noticeId=2188073:objectType=note</id> - <title>New note by safebot</title> - <content type="html">#&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://gs.smuglo.li/tag/cheers&quot; rel=&quot;tag&quot;&gt;cheers&lt;/a&gt;&lt;/span&gt; &lt;a href=&quot;https://gs.smuglo.li/file/5099e73c83da778cd032a721e96880f99a868b712be2975d08238547a5ba06c7.jpg&quot; title=&quot;https://gs.smuglo.li/file/5099e73c83da778cd032a721e96880f99a868b712be2975d08238547a5ba06c7.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/456444&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/notice/2188073"/> - <status_net notice_id="2061504"></status_net> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1061934"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1061934" local_id="1061934" ref="https://gs.smuglo.li/conversation/1009429">https://gs.smuglo.li/conversation/1009429</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="cheers"></category> - <source> - <id>https://gs.smuglo.li/api/statuses/user_timeline/25857.atom</id> - <title>safebot</title> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/safebot"/> - <link rel="self" type="application/atom+xml" href="https://gs.smuglo.li/api/statuses/user_timeline/25857.atom"/> - <icon>https://social.heldscal.la/avatar/25719-original-20161215233234.jpeg</icon> - <updated>2017-05-05T12:00:57+00:00</updated> - </source> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1061934"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1061934" local_id="1061934" ref="https://gs.smuglo.li/conversation/1009429">https://gs.smuglo.li/conversation/1009429</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/2061871.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061871.atom"/> - <statusnet:notice_info local_id="2061871" source="api" repeat_of="2061504"></statusnet:notice_info> -</entry> -<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> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2061696:2017-05-05T09:06:10+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;br /&gt; &lt;span class=&quot;greentext&quot;&gt;&amp;gt; (((common era)))&lt;/span&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061781"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T09:06:10+00:00</published> - <updated>2017-05-05T09:06:10+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=2827918: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;br /&gt; &lt;span class=&quot;greentext&quot;&gt;&amp;gt; (((common era)))&lt;/span&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2827918"/> - <status_net notice_id="2061696"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2827918:objectType=comment" href="https://shitposter.club/notice/2827918"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2827918"/> - <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/2061781.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061781.atom"/> - <statusnet:notice_info local_id="2061781" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:note:2061673:2017-05-05T08:58:28+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by moonman: discussion is one thing but any argument I've heard over and over again for the last three decades is going to go unanswered.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061702"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T08:58:28+00:00</published> - <updated>2017-05-05T08:58:28+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-05-05:noticeId=2827895:objectType=note</id> - <title>New note by moonman</title> - <content type="html">discussion is one thing but any argument I've heard over and over again for the last three decades is going to go unanswered.</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2827895"/> - <status_net notice_id="2061673"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2827895:objectType=note" href="https://shitposter.club/notice/2827895"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2827895"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1062026"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1062026" local_id="1062026" ref="https://shitposter.club/conversation/1390494">https://shitposter.club/conversation/1390494</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/2061702.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061702.atom"/> - <statusnet:notice_info local_id="2061702" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2061280:2017-05-05T08:47:38+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; sex is for procreation and as an expression of intimacy between commited couples, it is a sacramental act</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061614"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T08:47:38+00:00</published> - <updated>2017-05-05T08:47:38+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=2827561: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; sex is for procreation and as an expression of intimacy between commited couples, it is a sacramental act</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2827561"/> - <status_net notice_id="2061280"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2827561:objectType=comment" href="https://shitposter.club/notice/2827561"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2827561"/> - <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/2061614.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061614.atom"/> - <statusnet:notice_info local_id="2061614" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:note:2061535:2017-05-05T08:40:55+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by fortune: What did Mickey Mouse get for Christmas?&lt;br /&gt; &lt;br /&gt; A Dan Quayle watch.&lt;br /&gt; &lt;br /&gt; -- heard from a Mike Dukakis field worker</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061544"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T08:40:55+00:00</published> - <updated>2017-05-05T08:40:55+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-05-05:noticeId=2061535:objectType=note</id> - <title>New note by fortune</title> - <content type="html">What did Mickey Mouse get for Christmas?&lt;br /&gt; &lt;br /&gt; A Dan Quayle watch.&lt;br /&gt; &lt;br /&gt; -- heard from a Mike Dukakis field worker</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061535"/> - <status_net notice_id="2061535"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:social.heldscal.la,2017-05-05:noticeId=2061535:objectType=note" href="https://social.heldscal.la/notice/2061535"></thr:in-reply-to> - <link rel="related" href="https://social.heldscal.la/notice/2061535"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1061954"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1061954" local_id="1061954" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=5185e5c145ee4762">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=5185e5c145ee4762</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/2061544.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061544.atom"/> - <statusnet:notice_info local_id="2061544" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2061421:2017-05-05T08:36:27+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by moonman: @&lt;a href=&quot;https://maly.io/users/sonya&quot; class=&quot;h-card mention&quot; title=&quot;Sonya Mann ✅&quot;&gt;sonya&lt;/a&gt; banned from 4chan. you better watch ou. i'm trouble, y'hear?</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061495"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T08:36:27+00:00</published> - <updated>2017-05-05T08:36:27+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=2827689:objectType=comment</id> - <title>New comment by moonman</title> - <content type="html">@&lt;a href=&quot;https://maly.io/users/sonya&quot; class=&quot;h-card mention&quot; title=&quot;Sonya Mann ✅&quot;&gt;sonya&lt;/a&gt; banned from 4chan. you better watch ou. i'm trouble, y'hear?</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2827689"/> - <status_net notice_id="2061421"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2827689:objectType=comment" href="https://shitposter.club/notice/2827689"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2827689"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1060861"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1060861" local_id="1060861" ref="https://shitposter.club/conversation/1389345">https://shitposter.club/conversation/1389345</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/2061495.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061495.atom"/> - <statusnet:notice_info local_id="2061495" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2061351:2017-05-05T08:28:03+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by moonman: @&lt;a href=&quot;https://social.heldscal.la/user/29138&quot; class=&quot;h-card mention&quot; title=&quot;Claes Wallin (韋嘉誠)&quot;&gt;clacke&lt;/a&gt; is that the sequel to Time Crisis</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061410"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T08:28:03+00:00</published> - <updated>2017-05-05T08:28:03+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=2827630:objectType=comment</id> - <title>New comment by moonman</title> - <content type="html">@&lt;a href=&quot;https://social.heldscal.la/user/29138&quot; class=&quot;h-card mention&quot; title=&quot;Claes Wallin (韋嘉誠)&quot;&gt;clacke&lt;/a&gt; is that the sequel to Time Crisis</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2827630"/> - <status_net notice_id="2061351"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2827630:objectType=comment" href="https://shitposter.club/notice/2827630"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2827630"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1056672"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1056672" local_id="1056672" ref="https://shitposter.club/conversation/1385528">https://shitposter.club/conversation/1385528</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/2061410.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061410.atom"/> - <statusnet:notice_info local_id="2061410" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-05-05:fave:23211:comment:2061339:2017-05-05T08:21:05+00:00</id> - <title>Favorite</title> - <content type="html">lambadalambda favorited something by hardbass2k8: @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; pretty sure it's money laundering</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061357"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-05-05T08:21:05+00:00</published> - <updated>2017-05-05T08:21:05+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=2827617:objectType=comment</id> - <title>New comment by hardbass2k8</title> - <content type="html">@&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card mention&quot; title=&quot;Constance Variable&quot;&gt;lambadalambda&lt;/a&gt; pretty sure it's money laundering</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2827617"/> - <status_net notice_id="2061339"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-05-05:noticeId=2827617:objectType=comment" href="https://shitposter.club/notice/2827617"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2827617"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1059050"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1059050" local_id="1059050" ref="https://shitposter.club/conversation/1387523">https://shitposter.club/conversation/1387523</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/2061357.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061357.atom"/> - <statusnet:notice_info local_id="2061357" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-05-05:noticeId=2061303:objectType=note</id> - <title>New note by lambadalambda</title> - <content type="html">It's got tattoos, it's got a pierced hood&lt;br /&gt; It's got generation X&lt;br /&gt; It's got lesbians, and vitriol&lt;br /&gt; And sadomasochistic latex sex&lt;br /&gt; It's got Mighty Morphin' power brokers&lt;br /&gt; And Tanya Harding nude&lt;br /&gt; Macrobiotic lacto-vegan non-confrontational free range food&lt;br /&gt; It's got the handshake, peace talk, non-aggression pact&lt;br /&gt; A multicultural integration of segregated historical facts&lt;br /&gt; &lt;br /&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/tag/nsfw&quot; rel=&quot;tag&quot;&gt;nsfw&lt;/a&gt;&lt;/span&gt; &lt;a href=&quot;https://social.heldscal.la/file/61c13b99c92f40ec4865e7a3830da340b187e3de70d94b8da38fd2138bbede3a.jpg&quot; title=&quot;https://social.heldscal.la/file/61c13b99c92f40ec4865e7a3830da340b187e3de70d94b8da38fd2138bbede3a.jpg&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-432199&quot;&gt;https://social.heldscal.la/attachment/432199&lt;/a&gt; &lt;a href=&quot;https://social.heldscal.la/file/a88bba1a324da68ee2cfdbcd1c4cde60bd9553298244d6f81731270b71aa80df.jpg&quot; title=&quot;https://social.heldscal.la/file/a88bba1a324da68ee2cfdbcd1c4cde60bd9553298244d6f81731270b71aa80df.jpg&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-432200&quot;&gt;https://social.heldscal.la/attachment/432200&lt;/a&gt; &lt;a href=&quot;https://social.heldscal.la/file/887329a303250e73dc2eea06b1f0512fcac4b9d1b534068f03c45f00d5b21c39.jpg&quot; title=&quot;https://social.heldscal.la/file/887329a303250e73dc2eea06b1f0512fcac4b9d1b534068f03c45f00d5b21c39.jpg&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-432201&quot;&gt;https://social.heldscal.la/attachment/432201&lt;/a&gt; &lt;a href=&quot;https://social.heldscal.la/file/6d7a1ec15c1368c4c68810434d24da528606fcbccdd1da97b25affafeeb6ffda.jpg&quot; title=&quot;https://social.heldscal.la/file/6d7a1ec15c1368c4c68810434d24da528606fcbccdd1da97b25affafeeb6ffda.jpg&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-432202&quot;&gt;https://social.heldscal.la/attachment/432202&lt;/a&gt; &lt;a href=&quot;https://social.heldscal.la/file/2f55f2bb028eb9be744cc82b35a6b86b496d8c3924c700aff55a872ff11df54c.jpg&quot; title=&quot;https://social.heldscal.la/file/2f55f2bb028eb9be744cc82b35a6b86b496d8c3924c700aff55a872ff11df54c.jpg&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-432203&quot;&gt;https://social.heldscal.la/attachment/432203&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2061303"/> - <status_net notice_id="2061303"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-05-05T08:17:08+00:00</published> - <updated>2017-05-05T08:17:08+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1061817"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1061817" local_id="1061817" ref="tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=bb6f4343036970e8">tag:social.heldscal.la,2017-05-05:objectType=thread:nonce=bb6f4343036970e8</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="nsfw"></category> - <link rel="enclosure" href="https://social.heldscal.la/file/61c13b99c92f40ec4865e7a3830da340b187e3de70d94b8da38fd2138bbede3a.jpg" type="image/jpeg" length="239712"/> - <link rel="enclosure" href="https://social.heldscal.la/file/a88bba1a324da68ee2cfdbcd1c4cde60bd9553298244d6f81731270b71aa80df.jpg" type="image/jpeg" length="185200"/> - <link rel="enclosure" href="https://social.heldscal.la/file/887329a303250e73dc2eea06b1f0512fcac4b9d1b534068f03c45f00d5b21c39.jpg" type="image/jpeg" length="292061"/> - <link rel="enclosure" href="https://social.heldscal.la/file/6d7a1ec15c1368c4c68810434d24da528606fcbccdd1da97b25affafeeb6ffda.jpg" type="image/jpeg" length="147280"/> - <link rel="enclosure" href="https://social.heldscal.la/file/2f55f2bb028eb9be744cc82b35a6b86b496d8c3924c700aff55a872ff11df54c.jpg" type="image/jpeg" length="164659"/> - <link rel="self" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061303.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2061303.atom"/> - <statusnet:notice_info local_id="2061303" source="Pleroma FE"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/tesla_mock/https___social.heldscal.la_api_statuses_user_timeline_29191.atom.xml b/test/fixtures/tesla_mock/https___social.heldscal.la_api_statuses_user_timeline_29191.atom.xml @@ -1,719 +0,0 @@ -<?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/29191.atom</id> - <title>shp timeline</title> - <subtitle>Updates from shp on social.heldscal.la!</subtitle> - <logo>https://social.heldscal.la/avatar/29191-96-20170421154949.jpeg</logo> - <updated>2017-05-05T11:57:06+00:00</updated> -<author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://social.heldscal.la/user/29191</uri> - <name>shp</name> - <summary>cofe</summary> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/shp"/> - <link rel="avatar" type="image/jpeg" media:width="735" media:height="735" href="https://social.heldscal.la/avatar/29191-original-20170421154949.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/29191-96-20170421154949.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/29191-48-20170421154949.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/29191-24-20170421161149.jpeg"/> - <poco:preferredUsername>shp</poco:preferredUsername> - <poco:displayName>shp</poco:displayName> - <poco:note>cofe</poco:note> - <poco:address> - <poco:formatted>cofe</poco:formatted> - </poco:address> - <followers url="https://social.heldscal.la/shp/subscribers"></followers> - <statusnet:profile_info local_id="29191"></statusnet:profile_info> -</author> - <link href="https://social.heldscal.la/shp" 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/api/statuses/user_timeline/29191.atom?max_id=1907936" rel="next" type="application/atom+xml"/> - <link href="https://social.heldscal.la/main/push/hub" rel="hub"/> - <link href="https://social.heldscal.la/main/salmon/user/29191" rel="salmon"/> - <link href="https://social.heldscal.la/main/salmon/user/29191" rel="http://salmon-protocol.org/ns/salmon-replies"/> - <link href="https://social.heldscal.la/main/salmon/user/29191" rel="http://salmon-protocol.org/ns/salmon-mention"/> - <link href="https://social.heldscal.la/api/statuses/user_timeline/29191.atom" rel="self" type="application/atom+xml"/> -<entry> - <id>tag:social.heldscal.la,2017-04-29:noticeId=1967657:objectType=note</id> - <title>shp repeated a notice by lain</title> - <content type="html">RT @&lt;a href=&quot;https://social.heldscal.la/user/37181&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;Lain Iwakura&quot;&gt;lain&lt;/a&gt; @&lt;a href=&quot;https://social.heldscal.la/user/29191&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;shp&quot;&gt;shp&lt;/a&gt; @&lt;a href=&quot;https://social.heldscal.la/user/23211&quot; class=&quot;h-card u-url p-nickname mention&quot;&gt;lambadalambda&lt;/a&gt; cofe.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1967657"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-04-29T18:19:34+00:00</published> - <updated>2017-04-29T18:19:34+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>https://pleroma.soykaf.com/activities/43d12c05-db3f-4f3d-bee1-d676f264490c</id> - <title></title> - <content type="html">&lt;a href=&quot;https://pleroma.soykaf.com/users/shp&quot;&gt;@shp&lt;/a&gt; &lt;a href=&quot;https://social.heldscal.la/user/23211&quot;&gt;@lambadalambda@social.heldscal.la&lt;/a&gt; cofe.</content> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/activities/43d12c05-db3f-4f3d-bee1-d676f264490c"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-29T18:14:36+00:00</published> - <updated>2017-04-29T18:14:36+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://pleroma.soykaf.com/users/lain</uri> - <name>lain</name> - <summary>Test account</summary> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="avatar" type="image/jpeg" media:width="250" media:height="202" href="https://social.heldscal.la/avatar/43188-original-20170429171039.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/43188-96-20170429172422.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/43188-48-20170429172422.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/43188-24-20170429181411.jpeg"/> - <poco:preferredUsername>lain</poco:preferredUsername> - <poco:displayName>Lain Iwakura</poco:displayName> - <poco:note>Test account</poco:note> - <statusnet:profile_info local_id="43188"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>https://pleroma.soykaf.com/activities/43d12c05-db3f-4f3d-bee1-d676f264490c</id> - <title>New note by lain</title> - <content type="html">&lt;a href=&quot;https://pleroma.soykaf.com/users/shp&quot;&gt;@shp&lt;/a&gt; &lt;a href=&quot;https://social.heldscal.la/user/23211&quot;&gt;@lambadalambda@social.heldscal.la&lt;/a&gt; cofe.</content> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/activities/43d12c05-db3f-4f3d-bee1-d676f264490c"/> - <status_net notice_id="1967581"></status_net> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1007769"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1007769" local_id="1007769" ref="tag:social.heldscal.la,2017-04-29:objectType=thread:nonce=e0b75431888efdab">tag:social.heldscal.la,2017-04-29:objectType=thread:nonce=e0b75431888efdab</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>https://pleroma.soykaf.com/users/lain/feed.atom</id> - <title>Lain Iwakura</title> - <link rel="alternate" type="text/html" href="https://pleroma.soykaf.com/users/lain"/> - <link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/users/lain/feed.atom"/> - <icon>https://social.heldscal.la/avatar/43188-96-20170429172422.jpeg</icon> - <updated>2017-05-05T08:38:03+00:00</updated> - </source> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1007769"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1007769" local_id="1007769" ref="tag:social.heldscal.la,2017-04-29:objectType=thread:nonce=e0b75431888efdab">tag:social.heldscal.la,2017-04-29:objectType=thread:nonce=e0b75431888efdab</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/1967657.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1967657.atom"/> - <statusnet:notice_info local_id="1967657" source="Qvitter" repeat_of="1967581"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:subscription:29191:person:29558:2017-04-27T17:26:37+00:00</id> - <title>shp (shp@social.heldscal.la)'s status on Thursday, 27-Apr-2017 17:26:37 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/shp&quot;&gt;shp&lt;/a&gt; started following &lt;a href=&quot;https://gs.smuglo.li/kfist&quot;&gt;KFist&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1933101"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-04-27T17:26:37+00:00</published> - <updated>2017-04-27T17:26:37+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://gs.smuglo.li/user/28051</id> - <title>KFist</title> - <summary>I stream thanks to @nepfag. I also drink, shitpost, and fly planes. I visited Japan and it changed my life. Do you love your station?</summary> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/kfist"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/29558-original-20170302030034.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/29558-original-20170302030034.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/29558-48-20170303232734.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/29558-24-20170304004149.jpeg"/> - <poco:preferredUsername>kfist</poco:preferredUsername> - <poco:displayName>KFist</poco:displayName> - <poco:note>I stream thanks to @nepfag. I also drink, shitpost, and fly planes. I visited Japan and it changed my life. Do you love your station?</poco:note> - <poco:urls> - <poco:type>homepage</poco:type> - <poco:value>http://smuglo.li:8000/stream.m3u</poco:value> - <poco:primary>true</poco:primary> - </poco:urls> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988472"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988472" local_id="988472" ref="tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=f766240d13ed9c2e">tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=f766240d13ed9c2e</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/1933101.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1933101.atom"/> - <statusnet:notice_info local_id="1933101" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:noticeId=1933030:objectType=note</id> - <title>shp repeated a notice by shpbot</title> - <content type="html">RT @&lt;a href=&quot;https://gs.archae.me/user/4687&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;shpbot&quot;&gt;shpbot&lt;/a&gt; &amp;gt;QuakeC</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1933030"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-04-27T17:21:10+00:00</published> - <updated>2017-04-27T17:21:10+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>tag:gs.archae.me,2017-04-27:noticeId=760881:objectType=note</id> - <title></title> - <content type="html">&lt;span class='greentext'&gt;&amp;gt;QuakeC&lt;/span&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.archae.me/notice/760881"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-27T17:15:13+00:00</published> - <updated>2017-04-27T17:15:13+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://gs.archae.me/user/4687</uri> - <name>shpbot</name> - <link rel="alternate" type="text/html" href="https://gs.archae.me/shpbot"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/31581-48-20170405170027.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/31581-24-20170405170342.jpeg"/> - <poco:preferredUsername>shpbot</poco:preferredUsername> - <poco:displayName>shpbot</poco:displayName> - <statusnet:profile_info local_id="31581"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.archae.me,2017-04-27:noticeId=760881:objectType=note</id> - <title>New note by shpbot</title> - <content type="html">&lt;span class='greentext'&gt;&amp;gt;QuakeC&lt;/span&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.archae.me/notice/760881"/> - <status_net notice_id="1932941"></status_net> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988397"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988397" local_id="988397" ref="https://gs.archae.me/conversation/318362">https://gs.archae.me/conversation/318362</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>https://gs.archae.me/api/statuses/user_timeline/4687.atom</id> - <title>shpbot</title> - <link rel="alternate" type="text/html" href="https://gs.archae.me/shpbot"/> - <link rel="self" type="application/atom+xml" href="https://gs.archae.me/api/statuses/user_timeline/4687.atom"/> - <icon>https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg</icon> - <updated>2017-05-05T11:45:08+00:00</updated> - </source> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988397"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988397" local_id="988397" ref="https://gs.archae.me/conversation/318362">https://gs.archae.me/conversation/318362</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/1933030.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1933030.atom"/> - <statusnet:notice_info local_id="1933030" source="Qvitter" repeat_of="1932941"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:subscription:29191:person:23226:2017-04-27T17:20:48+00:00</id> - <title>shp (shp@social.heldscal.la)'s status on Thursday, 27-Apr-2017 17:20:48 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/shp&quot;&gt;shp&lt;/a&gt; started following &lt;a href=&quot;http://quitter.se/taknamay&quot;&gt;Internet Turtle Ⓐ 🏴 ✅&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1933025"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-04-27T17:20:48+00:00</published> - <updated>2017-04-27T17:20:48+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>http://quitter.se/user/115823</id> - <title>Internet Turtle Ⓐ 🏴 ✅</title> - <summary>Scheme programmer, Novice esperantist, Spiritual naturalist - Will listen to your problems for free - XMPP: DarkDungeons94 at chatme.im</summary> - <link rel="alternate" type="text/html" href="http://quitter.se/taknamay"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/23226-original-20170427130915.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/23226-original-20170427130915.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/23226-48-20170427130918.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/23226-24-20170427171808.jpeg"/> - <poco:preferredUsername>taknamay</poco:preferredUsername> - <poco:displayName>Internet Turtle Ⓐ 🏴 ✅</poco:displayName> - <poco:note>Scheme programmer, Novice esperantist, Spiritual naturalist - Will listen to your problems for free - XMPP: DarkDungeons94 at chatme.im</poco:note> - <poco:address> - <poco:formatted>New Jersey, United States</poco:formatted> - </poco:address> - <poco:urls> - <poco:type>homepage</poco:type> - <poco:value>https://quitter.se/taknamay</poco:value> - <poco:primary>true</poco:primary> - </poco:urls> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988439"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988439" local_id="988439" ref="tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=a66b1fb22020c152">tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=a66b1fb22020c152</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/1933025.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1933025.atom"/> - <statusnet:notice_info local_id="1933025" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:subscription:29191:person:29302:2017-04-27T17:20:33+00:00</id> - <title>shp (shp@social.heldscal.la)'s status on Thursday, 27-Apr-2017 17:20:33 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/shp&quot;&gt;shp&lt;/a&gt; started following &lt;a href=&quot;https://icosahedron.website/@Trev&quot;&gt;Chillidan Stormrave&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1933022"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-04-27T17:20:33+00:00</published> - <updated>2017-04-27T17:20:33+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://icosahedron.website/users/Trev</id> - <title>Trev Prime</title> - <summary>web tech, music, ethics. radical individualist. kinda queer. love thy neighbor. always open for conversation. </summary> - <link rel="alternate" type="text/html" href="https://icosahedron.website/@Trev"/> - <link rel="avatar" type="image/png" media:width="120" media:height="120" href="https://social.heldscal.la/avatar/29302-original-20170417171941.png"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/29302-96-20170417171942.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/29302-48-20170417171942.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/29302-24-20170417180438.png"/> - <poco:preferredUsername>trev</poco:preferredUsername> - <poco:displayName>Trev Prime</poco:displayName> - <poco:note>web tech, music, ethics. radical individualist. kinda queer. love thy neighbor. always open for conversation. </poco:note> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988436"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988436" local_id="988436" ref="tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=781c05bd64ad9520">tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=781c05bd64ad9520</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/1933022.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1933022.atom"/> - <statusnet:notice_info local_id="1933022" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:subscription:29191:person:29367:2017-04-27T17:20:27+00:00</id> - <title>shp (shp@social.heldscal.la)'s status on Thursday, 27-Apr-2017 17:20:27 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/shp&quot;&gt;shp&lt;/a&gt; started following &lt;a href=&quot;https://gs.kawa-kun.com/aya&quot;&gt;射命丸 文&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1933020"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-04-27T17:20:27+00:00</published> - <updated>2017-04-27T17:20:27+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://gs.kawa-kun.com/user/4885</id> - <title>射命丸 文</title> - <summary>Traditional Reporter of Fantasy</summary> - <link rel="alternate" type="text/html" href="https://gs.kawa-kun.com/aya"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/29367-original-20170322091904.png"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/29367-original-20170322091904.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/29367-48-20170322103327.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/29367-24-20170322185131.png"/> - <poco:preferredUsername>aya</poco:preferredUsername> - <poco:displayName>射命丸 文</poco:displayName> - <poco:note>Traditional Reporter of Fantasy</poco:note> - <poco:address> - <poco:formatted>Gensōkyō</poco:formatted> - </poco:address> - <poco:urls> - <poco:type>homepage</poco:type> - <poco:value>https://danbooru.donmai.us</poco:value> - <poco:primary>true</poco:primary> - </poco:urls> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988435"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988435" local_id="988435" ref="tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=5921da7a934e47ca">tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=5921da7a934e47ca</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/1933020.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1933020.atom"/> - <statusnet:notice_info local_id="1933020" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:subscription:29191:person:27773:2017-04-27T17:20:18+00:00</id> - <title>shp (shp@social.heldscal.la)'s status on Thursday, 27-Apr-2017 17:20:18 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/shp&quot;&gt;shp&lt;/a&gt; started following &lt;a href=&quot;https://gs.smuglo.li/japananon&quot;&gt;JapanAnon&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1933017"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-04-27T17:20:18+00:00</published> - <updated>2017-04-27T17:20:18+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://gs.smuglo.li/user/27299</id> - <title>JapanAnon</title> - <summary>匿名でしていてね!</summary> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/japananon"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/27773-original-20170102074719.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/27773-original-20170102074719.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/27773-48-20170103173058.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/27773-24-20170103173058.jpeg"/> - <poco:preferredUsername>japananon</poco:preferredUsername> - <poco:displayName>JapanAnon</poco:displayName> - <poco:note>匿名でしていてね!</poco:note> - <poco:address> - <poco:formatted>ワイヤード</poco:formatted> - </poco:address> - <poco:urls> - <poco:type>homepage</poco:type> - <poco:value>http://www.anonymous-japan.org</poco:value> - <poco:primary>true</poco:primary> - </poco:urls> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988434"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988434" local_id="988434" ref="tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=ae3d819865886cba">tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=ae3d819865886cba</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/1933017.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1933017.atom"/> - <statusnet:notice_info local_id="1933017" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:subscription:29191:person:36560:2017-04-27T17:19:30+00:00</id> - <title>shp (shp@social.heldscal.la)'s status on Thursday, 27-Apr-2017 17:19:30 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/shp&quot;&gt;shp&lt;/a&gt; started following &lt;a href=&quot;https://shitposter.club/wareya&quot;&gt;wareya&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1933001"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-04-27T17:19:30+00:00</published> - <updated>2017-04-27T17:19:30+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://shitposter.club/user/15439</id> - <title>wareya</title> - <summary>Who are you to defy such a perfect being that is the machine? 日本語難しいけど頑張るぜ github.com/wareya wareya.moe Short: reya or war, never &quot;ware&quot;</summary> - <link rel="alternate" type="text/html" href="https://shitposter.club/wareya"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/36560-original-20170414073546.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/36560-original-20170414073546.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/36560-48-20170414075036.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/36560-24-20170427171930.jpeg"/> - <poco:preferredUsername>wareya</poco:preferredUsername> - <poco:displayName>wareya</poco:displayName> - <poco:note>Who are you to defy such a perfect being that is the machine? 日本語難しいけど頑張るぜ github.com/wareya wareya.moe Short: reya or war, never &quot;ware&quot;</poco:note> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988426"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988426" local_id="988426" ref="tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=bd88a3cd20b5a418">tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=bd88a3cd20b5a418</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/1933001.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1933001.atom"/> - <statusnet:notice_info local_id="1933001" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:subscription:29191:person:41176:2017-04-27T17:19:21+00:00</id> - <title>shp (shp@social.heldscal.la)'s status on Thursday, 27-Apr-2017 17:19:21 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/shp&quot;&gt;shp&lt;/a&gt; started following &lt;a href=&quot;https://hakui.club/takeshitakenji&quot;&gt;竹下憲二 (白)&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1932999"/> - <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> - <published>2017-04-27T17:19:21+00:00</published> - <updated>2017-04-27T17:19:21+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://hakui.club/user/6</id> - <title>竹下憲二 (白)</title> - <summary>Oh boy.</summary> - <link rel="alternate" type="text/html" href="https://hakui.club/takeshitakenji"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/41176-original-20170428153916.png"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/41176-original-20170428153916.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/41176-48-20170428153926.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/41176-24-20170428160801.png"/> - <poco:preferredUsername>takeshitakenji</poco:preferredUsername> - <poco:displayName>竹下憲二 (白)</poco:displayName> - <poco:note>Oh boy.</poco:note> - <poco:address> - <poco:formatted>Seattle, WA</poco:formatted> - </poco:address> - <poco:urls> - <poco:type>homepage</poco:type> - <poco:value>http://gs.kawa-kun.com</poco:value> - <poco:primary>true</poco:primary> - </poco:urls> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988424"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988424" local_id="988424" ref="tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=b139a673deba6963">tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=b139a673deba6963</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/1932999.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1932999.atom"/> - <statusnet:notice_info local_id="1932999" source="activity"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:fave:29191:note:1932205:2017-04-27T17:17:46+00:00</id> - <title>Favorite</title> - <content type="html">shp favorited something by dolus: Looks like Merry is pussing out and caving to pressure. Sad. &lt;a href=&quot;https://gs.smuglo.li/file/23e37de3c321248d3f322d8ec042372914568ab4c9431a94e568a61b8146587f.png&quot; title=&quot;https://gs.smuglo.li/file/23e37de3c321248d3f322d8ec042372914568ab4c9431a94e568a61b8146587f.png&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432294&lt;/a&gt; &lt;a href=&quot;https://gs.smuglo.li/file/e5a9549a19986d59d51750090910f47c186787adf02b2b6ac58df37556887297.png&quot; title=&quot;https://gs.smuglo.li/file/e5a9549a19986d59d51750090910f47c186787adf02b2b6ac58df37556887297.png&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432295&lt;/a&gt; &lt;a href=&quot;https://gs.smuglo.li/file/2fdfabbc8ab0b8dc135903a8c48c29b440d1f97446b98ced4ad14a54d3b5d41f.png&quot; title=&quot;https://gs.smuglo.li/file/2fdfabbc8ab0b8dc135903a8c48c29b440d1f97446b98ced4ad14a54d3b5d41f.png&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432296&lt;/a&gt; &lt;a href=&quot;https://gs.smuglo.li/file/af605d7c6fe3a8c26c6d334c2a8e0005f7e86a266f14a5b3755e7d3ac4e226de.png&quot; title=&quot;https://gs.smuglo.li/file/af605d7c6fe3a8c26c6d334c2a8e0005f7e86a266f14a5b3755e7d3ac4e226de.png&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432297&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1932976"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-04-27T17:17:46+00:00</published> - <updated>2017-04-27T17:17:46+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.smuglo.li,2017-04-27:noticeId=2065465:objectType=note</id> - <title>New note by dolus</title> - <content type="html">Looks like Merry is pussing out and caving to pressure. Sad. &lt;a href=&quot;https://gs.smuglo.li/file/23e37de3c321248d3f322d8ec042372914568ab4c9431a94e568a61b8146587f.png&quot; title=&quot;https://gs.smuglo.li/file/23e37de3c321248d3f322d8ec042372914568ab4c9431a94e568a61b8146587f.png&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432294&lt;/a&gt; &lt;a href=&quot;https://gs.smuglo.li/file/e5a9549a19986d59d51750090910f47c186787adf02b2b6ac58df37556887297.png&quot; title=&quot;https://gs.smuglo.li/file/e5a9549a19986d59d51750090910f47c186787adf02b2b6ac58df37556887297.png&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432295&lt;/a&gt; &lt;a href=&quot;https://gs.smuglo.li/file/2fdfabbc8ab0b8dc135903a8c48c29b440d1f97446b98ced4ad14a54d3b5d41f.png&quot; title=&quot;https://gs.smuglo.li/file/2fdfabbc8ab0b8dc135903a8c48c29b440d1f97446b98ced4ad14a54d3b5d41f.png&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432296&lt;/a&gt; &lt;a href=&quot;https://gs.smuglo.li/file/af605d7c6fe3a8c26c6d334c2a8e0005f7e86a266f14a5b3755e7d3ac4e226de.png&quot; title=&quot;https://gs.smuglo.li/file/af605d7c6fe3a8c26c6d334c2a8e0005f7e86a266f14a5b3755e7d3ac4e226de.png&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432297&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/notice/2065465"/> - <status_net notice_id="1932205"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:gs.smuglo.li,2017-04-27:noticeId=2065465:objectType=note" href="https://gs.smuglo.li/notice/2065465"></thr:in-reply-to> - <link rel="related" href="https://gs.smuglo.li/notice/2065465"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/987894"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/987894" local_id="987894" ref="https://gs.smuglo.li/conversation/927473">https://gs.smuglo.li/conversation/927473</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/1932976.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1932976.atom"/> - <statusnet:notice_info local_id="1932976" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:fave:29191:note:1932492:2017-04-27T17:13:55+00:00</id> - <title>Favorite</title> - <content type="html">shp favorited something by zemichi: &lt;a href=&quot;https://gs.smuglo.li/file/1d45ea4ffc95f15037f361b56ad6b89f8451b70ad1ff7a03b7bb0345b8e2227c.jpg&quot; title=&quot;https://gs.smuglo.li/file/1d45ea4ffc95f15037f361b56ad6b89f8451b70ad1ff7a03b7bb0345b8e2227c.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432344&lt;/a&gt;&lt;br /&gt; that's a lot of loli</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1932922"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-04-27T17:13:55+00:00</published> - <updated>2017-04-27T17:13:55+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.smuglo.li,2017-04-27:noticeId=2065713:objectType=note</id> - <title>New note by zemichi</title> - <content type="html">&lt;a href=&quot;https://gs.smuglo.li/file/1d45ea4ffc95f15037f361b56ad6b89f8451b70ad1ff7a03b7bb0345b8e2227c.jpg&quot; title=&quot;https://gs.smuglo.li/file/1d45ea4ffc95f15037f361b56ad6b89f8451b70ad1ff7a03b7bb0345b8e2227c.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432344&lt;/a&gt;&lt;br /&gt; that's a lot of loli</content> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/notice/2065713"/> - <status_net notice_id="1932492"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:gs.smuglo.li,2017-04-27:noticeId=2065713:objectType=note" href="https://gs.smuglo.li/notice/2065713"></thr:in-reply-to> - <link rel="related" href="https://gs.smuglo.li/notice/2065713"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988113"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988113" local_id="988113" ref="https://gs.smuglo.li/conversation/927673">https://gs.smuglo.li/conversation/927673</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/1932922.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1932922.atom"/> - <statusnet:notice_info local_id="1932922" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:fave:29191:note:1932559:2017-04-27T17:12:46+00:00</id> - <title>Favorite</title> - <content type="html">shp favorited something by gsimg: &lt;a href=&quot;https://gs.kawa-kun.com/file/3435c5cafda46f31cad5abb5837b3521b7b458198507073a496f4d10bad3633b.jpg&quot; title=&quot;https://gs.kawa-kun.com/file/3435c5cafda46f31cad5abb5837b3521b7b458198507073a496f4d10bad3633b.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.kawa-kun.com/file/3435c5cafda46f31cad5abb5837b3521b7b458198507073a496f4d10bad3633b.jpg&lt;/a&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://gs.kawa-kun.com/tag/nsfw&quot; rel=&quot;tag&quot;&gt;nsfw&lt;/a&gt;&lt;/span&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1932894"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-04-27T17:12:46+00:00</published> - <updated>2017-04-27T17:12:46+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.kawa-kun.com,2017-04-27:noticeId=1608309:objectType=note</id> - <title>New note by gsimg</title> - <content type="html">&lt;a href=&quot;https://gs.kawa-kun.com/file/3435c5cafda46f31cad5abb5837b3521b7b458198507073a496f4d10bad3633b.jpg&quot; title=&quot;https://gs.kawa-kun.com/file/3435c5cafda46f31cad5abb5837b3521b7b458198507073a496f4d10bad3633b.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.kawa-kun.com/file/3435c5cafda46f31cad5abb5837b3521b7b458198507073a496f4d10bad3633b.jpg&lt;/a&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://gs.kawa-kun.com/tag/nsfw&quot; rel=&quot;tag&quot;&gt;nsfw&lt;/a&gt;&lt;/span&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.kawa-kun.com/notice/1608309"/> - <status_net notice_id="1932559"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:gs.kawa-kun.com,2017-04-27:noticeId=1608309:objectType=note" href="https://gs.kawa-kun.com/notice/1608309"></thr:in-reply-to> - <link rel="related" href="https://gs.kawa-kun.com/notice/1608309"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988157"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988157" local_id="988157" ref="https://gs.kawa-kun.com/conversation/690817">https://gs.kawa-kun.com/conversation/690817</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/1932894.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1932894.atom"/> - <statusnet:notice_info local_id="1932894" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:fave:29191:note:1932601:2017-04-27T17:12:28+00:00</id> - <title>Favorite</title> - <content type="html">shp favorited something by zemichi: &lt;a href=&quot;https://gs.smuglo.li/file/5d9114fafea7b9866c9d852bcfeaf66aade65ae26149758346bc5ade7e3fa8f0.jpg&quot; title=&quot;https://gs.smuglo.li/file/5d9114fafea7b9866c9d852bcfeaf66aade65ae26149758346bc5ade7e3fa8f0.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432372&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1932888"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-04-27T17:12:28+00:00</published> - <updated>2017-04-27T17:12:28+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.smuglo.li,2017-04-27:noticeId=2065821:objectType=note</id> - <title>New note by zemichi</title> - <content type="html">&lt;a href=&quot;https://gs.smuglo.li/file/5d9114fafea7b9866c9d852bcfeaf66aade65ae26149758346bc5ade7e3fa8f0.jpg&quot; title=&quot;https://gs.smuglo.li/file/5d9114fafea7b9866c9d852bcfeaf66aade65ae26149758346bc5ade7e3fa8f0.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://gs.smuglo.li/attachment/432372&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.smuglo.li/notice/2065821"/> - <status_net notice_id="1932601"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:gs.smuglo.li,2017-04-27:noticeId=2065821:objectType=note" href="https://gs.smuglo.li/notice/2065821"></thr:in-reply-to> - <link rel="related" href="https://gs.smuglo.li/notice/2065821"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988189"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988189" local_id="988189" ref="https://gs.smuglo.li/conversation/927760">https://gs.smuglo.li/conversation/927760</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/1932888.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1932888.atom"/> - <statusnet:notice_info local_id="1932888" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-27:noticeId=1932867:objectType=note</id> - <title>shp repeated a notice by shpbot</title> - <content type="html">RT @&lt;a href=&quot;https://gs.archae.me/user/4687&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;shpbot&quot;&gt;shpbot&lt;/a&gt; &lt;a href=&quot;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&quot; title=&quot;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-237676&quot;&gt;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&lt;/a&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/tag/2hu&quot; rel=&quot;tag&quot;&gt;2hu&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/tag/ordinarymagician&quot; rel=&quot;tag&quot;&gt;ordinarymagician&lt;/a&gt;&lt;/span&gt; :thinking: &lt;a href=&quot;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&quot; title=&quot;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-312306&quot;&gt;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1932867"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-04-27T17:11:35+00:00</published> - <updated>2017-04-27T17:11:35+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>tag:gs.archae.me,2017-04-27:noticeId=760830:objectType=note</id> - <title></title> - <content type="html">&lt;a href=&quot;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&quot; title=&quot;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&lt;/a&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://gs.archae.me/tag/2hu&quot; rel=&quot;tag&quot;&gt;2hu&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://gs.archae.me/tag/ordinarymagician&quot; rel=&quot;tag&quot;&gt;ordinarymagician&lt;/a&gt;&lt;/span&gt; :thinking: &lt;a href=&quot;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&quot; title=&quot;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.archae.me/notice/760830"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-27T17:00:08+00:00</published> - <updated>2017-04-27T17:00:08+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://gs.archae.me/user/4687</uri> - <name>shpbot</name> - <link rel="alternate" type="text/html" href="https://gs.archae.me/shpbot"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/31581-48-20170405170027.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/31581-24-20170405170342.jpeg"/> - <poco:preferredUsername>shpbot</poco:preferredUsername> - <poco:displayName>shpbot</poco:displayName> - <statusnet:profile_info local_id="31581"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.archae.me,2017-04-27:noticeId=760830:objectType=note</id> - <title>New note by shpbot</title> - <content type="html">&lt;a href=&quot;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&quot; title=&quot;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://shitposter.club/file/cbf7fbbee1127a9870e871305ca7de70f1eb1bbb79ffe5b3b0f33e37514d14d8.jpg&lt;/a&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://gs.archae.me/tag/2hu&quot; rel=&quot;tag&quot;&gt;2hu&lt;/a&gt;&lt;/span&gt; #&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://gs.archae.me/tag/ordinarymagician&quot; rel=&quot;tag&quot;&gt;ordinarymagician&lt;/a&gt;&lt;/span&gt; :thinking: &lt;a href=&quot;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&quot; title=&quot;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://shitposter.club/file/abf3f82d9ce28d2293d858af26c75bb5d4fdd091c0d90ca7bc72ea7efba220e4.jpg&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.archae.me/notice/760830"/> - <status_net notice_id="1932673"></status_net> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988229"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988229" local_id="988229" ref="https://gs.archae.me/conversation/318317">https://gs.archae.me/conversation/318317</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="2hu"></category> - <category term="ordinarymagician"></category> - <source> - <id>https://gs.archae.me/api/statuses/user_timeline/4687.atom</id> - <title>shpbot</title> - <link rel="alternate" type="text/html" href="https://gs.archae.me/shpbot"/> - <link rel="self" type="application/atom+xml" href="https://gs.archae.me/api/statuses/user_timeline/4687.atom"/> - <icon>https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg</icon> - <updated>2017-05-05T11:45:08+00:00</updated> - </source> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988229"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988229" local_id="988229" ref="https://gs.archae.me/conversation/318317">https://gs.archae.me/conversation/318317</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/1932867.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1932867.atom"/> - <statusnet:notice_info local_id="1932867" source="api" repeat_of="1932673"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-04-27:noticeId=1932815:objectType=note</id> - <title>New note by shp</title> - <content type="html">federation issues with SPC atm it seems</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1932815"/> - <status_net notice_id="1932815"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-27T17:08:55+00:00</published> - <updated>2017-04-27T17:08:55+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/988321"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/988321" local_id="988321" ref="tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=645a13c841f51769">tag:social.heldscal.la,2017-04-27:objectType=thread:nonce=645a13c841f51769</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/1932815.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1932815.atom"/> - <statusnet:notice_info local_id="1932815" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-26:fave:29191:note:1907285:2017-04-26T06:59:07+00:00</id> - <title>Favorite</title> - <content type="html">shp favorited something by lambadalambda: Is this the most offensive video on the net? &lt;a href=&quot;https://social.heldscal.la/file/4c34bfb81a8155c265031bc48f7e69c29eb0d2941c57daf63f80e17b0e2e5f47.webm&quot; title=&quot;https://social.heldscal.la/file/4c34bfb81a8155c265031bc48f7e69c29eb0d2941c57daf63f80e17b0e2e5f47.webm&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://social.heldscal.la/attachment/402251&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1907959"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-04-26T06:59:07+00:00</published> - <updated>2017-04-26T06:59:07+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-04-26:noticeId=1907285:objectType=note</id> - <title>New note by lambadalambda</title> - <content type="html">Is this the most offensive video on the net? &lt;a href=&quot;https://social.heldscal.la/file/4c34bfb81a8155c265031bc48f7e69c29eb0d2941c57daf63f80e17b0e2e5f47.webm&quot; title=&quot;https://social.heldscal.la/file/4c34bfb81a8155c265031bc48f7e69c29eb0d2941c57daf63f80e17b0e2e5f47.webm&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-402251&quot;&gt;https://social.heldscal.la/attachment/402251&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1907285"/> - <status_net notice_id="1907285"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:social.heldscal.la,2017-04-26:noticeId=1907285:objectType=note" href="https://social.heldscal.la/notice/1907285"></thr:in-reply-to> - <link rel="related" href="https://social.heldscal.la/notice/1907285"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/972605"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/972605" local_id="972605" ref="tag:social.heldscal.la,2017-04-26:objectType=thread:nonce=07b02e1328f456af">tag:social.heldscal.la,2017-04-26:objectType=thread:nonce=07b02e1328f456af</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/1907959.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1907959.atom"/> - <statusnet:notice_info local_id="1907959" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-26:noticeId=1907951:objectType=note</id> - <title>shp repeated a notice by shpbot</title> - <content type="html">RT @&lt;a href=&quot;https://gs.archae.me/user/4687&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;shpbot&quot;&gt;shpbot&lt;/a&gt; &lt;a href=&quot;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&quot; title=&quot;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-346198&quot;&gt;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1907951"/> - <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> - <published>2017-04-26T06:58:19+00:00</published> - <updated>2017-04-26T06:58:19+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> - <id>tag:gs.archae.me,2017-04-26:noticeId=752596:objectType=note</id> - <title></title> - <content type="html">&lt;a href=&quot;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&quot; title=&quot;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.archae.me/notice/752596"/> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-26T06:15:07+00:00</published> - <updated>2017-04-26T06:15:07+00:00</updated> - <author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://gs.archae.me/user/4687</uri> - <name>shpbot</name> - <link rel="alternate" type="text/html" href="https://gs.archae.me/shpbot"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="https://social.heldscal.la/avatar/31581-48-20170405170027.jpeg"/> - <link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="https://social.heldscal.la/avatar/31581-24-20170405170342.jpeg"/> - <poco:preferredUsername>shpbot</poco:preferredUsername> - <poco:displayName>shpbot</poco:displayName> - <statusnet:profile_info local_id="31581"></statusnet:profile_info> - </author> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:gs.archae.me,2017-04-26:noticeId=752596:objectType=note</id> - <title>New note by shpbot</title> - <content type="html">&lt;a href=&quot;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&quot; title=&quot;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://shitposter.club/file/718db06b564841331c72f9df767f8c9459e20c4dddbf0d4e61cd08ecbee7739d.jpg&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://gs.archae.me/notice/752596"/> - <status_net notice_id="1907331"></status_net> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/972636"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/972636" local_id="972636" ref="https://gs.archae.me/conversation/314010">https://gs.archae.me/conversation/314010</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <source> - <id>https://gs.archae.me/api/statuses/user_timeline/4687.atom</id> - <title>shpbot</title> - <link rel="alternate" type="text/html" href="https://gs.archae.me/shpbot"/> - <link rel="self" type="application/atom+xml" href="https://gs.archae.me/api/statuses/user_timeline/4687.atom"/> - <icon>https://social.heldscal.la/avatar/31581-original-20170405170019.jpeg</icon> - <updated>2017-05-05T11:45:08+00:00</updated> - </source> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/972636"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/972636" local_id="972636" ref="https://gs.archae.me/conversation/314010">https://gs.archae.me/conversation/314010</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/1907951.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1907951.atom"/> - <statusnet:notice_info local_id="1907951" source="api" repeat_of="1907331"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-26:fave:29191:note:1907341:2017-04-26T06:58:16+00:00</id> - <title>Favorite</title> - <content type="html">shp favorited something by moonman: &lt;a href=&quot;https://shitposter.club/file/1377b0894e983599c11e739e406243cabed9f8af7961a2550ecaf97e32de8e60.jpg&quot; title=&quot;https://shitposter.club/file/1377b0894e983599c11e739e406243cabed9f8af7961a2550ecaf97e32de8e60.jpg&quot; class=&quot;attachment&quot; rel=&quot;nofollow&quot;&gt;https://shitposter.club/attachment/630989&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1907949"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-04-26T06:58:16+00:00</published> - <updated>2017-04-26T06:58:16+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2017-04-26:noticeId=2681941:objectType=note</id> - <title>New note by moonman</title> - <content type="html">&lt;a href=&quot;https://shitposter.club/file/1377b0894e983599c11e739e406243cabed9f8af7961a2550ecaf97e32de8e60.jpg&quot; title=&quot;https://shitposter.club/file/1377b0894e983599c11e739e406243cabed9f8af7961a2550ecaf97e32de8e60.jpg&quot; class=&quot;attachment&quot; rel=&quot;nofollow&quot;&gt;https://shitposter.club/attachment/630989&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/2681941"/> - <status_net notice_id="1907341"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:shitposter.club,2017-04-26:noticeId=2681941:objectType=note" href="https://shitposter.club/notice/2681941"></thr:in-reply-to> - <link rel="related" href="https://shitposter.club/notice/2681941"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/972646"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/972646" local_id="972646" ref="https://shitposter.club/conversation/1300990">https://shitposter.club/conversation/1300990</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/1907949.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1907949.atom"/> - <statusnet:notice_info local_id="1907949" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:social.heldscal.la,2017-04-26:fave:29191:comment:1907412:2017-04-26T06:57:56+00:00</id> - <title>Favorite</title> - <content type="html">shp favorited something by lambadalambda: @&lt;a href=&quot;https://gs.smuglo.li/user/2&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;nepfag&quot;&gt;nepfag&lt;/a&gt; &lt;a href=&quot;https://cherubini.casa/why-i-shut-down-wizards-town-and-left-mastodon-6d4e631346b3?source=linkShare-89c2f851e979-1493184822&amp;amp;gi=a6a47c5466a0&quot; title=&quot;https://cherubini.casa/why-i-shut-down-wizards-town-and-left-mastodon-6d4e631346b3?source=linkShare-89c2f851e979-1493184822&amp;amp;gi=a6a47c5466a0&quot; rel=&quot;nofollow noreferrer&quot; class=&quot;attachment&quot;&gt;https://social.heldscal.la/url/402273&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1907947"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2017-04-26T06:57:56+00:00</published> - <updated>2017-04-26T06:57:56+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:social.heldscal.la,2017-04-26:noticeId=1907412:objectType=comment</id> - <title>New comment by lambadalambda</title> - <content type="html">@&lt;a href=&quot;https://gs.smuglo.li/user/2&quot; class=&quot;h-card u-url p-nickname mention&quot; title=&quot;nepfag&quot;&gt;nepfag&lt;/a&gt; &lt;a href=&quot;https://cherubini.casa/why-i-shut-down-wizards-town-and-left-mastodon-6d4e631346b3?source=linkShare-89c2f851e979-1493184822&amp;amp;gi=a6a47c5466a0&quot; title=&quot;https://cherubini.casa/why-i-shut-down-wizards-town-and-left-mastodon-6d4e631346b3?source=linkShare-89c2f851e979-1493184822&amp;amp;gi=a6a47c5466a0&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-402273&quot;&gt;https://social.heldscal.la/url/402273&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1907412"/> - <status_net notice_id="1907412"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:social.heldscal.la,2017-04-26:noticeId=1907412:objectType=comment" href="https://social.heldscal.la/notice/1907412"></thr:in-reply-to> - <link rel="related" href="https://social.heldscal.la/notice/1907412"/> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/972634"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/972634" local_id="972634" ref="tag:social.heldscal.la,2017-04-26:objectType=thread:nonce=85c21eda7aaa7259">tag:social.heldscal.la,2017-04-26:objectType=thread:nonce=85c21eda7aaa7259</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/1907947.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1907947.atom"/> - <statusnet:notice_info local_id="1907947" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:social.heldscal.la,2017-04-26:noticeId=1907942:objectType=note</id> - <title>New note by shp</title> - <content type="html">#&lt;span class=&quot;tag&quot;&gt;&lt;a href=&quot;https://social.heldscal.la/tag/cofe&quot; rel=&quot;tag&quot;&gt;cofe&lt;/a&gt;&lt;/span&gt; time my friends &lt;a href=&quot;https://social.heldscal.la/file/ec254b45b3a86ff74bc08bc7e065cb681d77cf7d4cedc9cdcf59e16adf311da3.png&quot; title=&quot;https://social.heldscal.la/file/ec254b45b3a86ff74bc08bc7e065cb681d77cf7d4cedc9cdcf59e16adf311da3.png&quot; rel=&quot;nofollow external noreferrer&quot; class=&quot;attachment&quot; id=&quot;attachment-402381&quot;&gt;https://social.heldscal.la/attachment/402381&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/1907942"/> - <status_net notice_id="1907942"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2017-04-26T06:57:18+00:00</published> - <updated>2017-04-26T06:57:18+00:00</updated> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/973042"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/973042" local_id="973042" ref="tag:social.heldscal.la,2017-04-26:objectType=thread:nonce=9c9d9373bccfaf70">tag:social.heldscal.la,2017-04-26:objectType=thread:nonce=9c9d9373bccfaf70</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <category term="cofe"></category> - <link rel="enclosure" href="https://social.heldscal.la/file/ec254b45b3a86ff74bc08bc7e065cb681d77cf7d4cedc9cdcf59e16adf311da3.png" type="image/png" length="3179103"/> - <link rel="self" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1907942.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/1907942.atom"/> - <statusnet:notice_info local_id="1907942" source="Pleroma FE"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/tesla_mock/sakamoto.atom b/test/fixtures/tesla_mock/sakamoto.atom @@ -1 +0,0 @@ -<?xml version="1.0"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0"><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056</id><title>New note by eal</title><content type="html">&lt;a href='https://shitposter.club/user/5381'&gt;@shpuld&lt;/a&gt; &lt;a href='https://pleroma.hjkos.com/users/hj'&gt;@hj&lt;/a&gt; IM NOT GAY DAD</content><published>2017-08-04T12:51:26.130592Z</published><updated>2017-08-04T12:51:26.130592Z</updated><ostatus:conversation>https://pleroma.hjkos.com/contexts/53093c74-2100-4bf4-aac6-66d1973d03ef</ostatus:conversation><link ref="https://pleroma.hjkos.com/contexts/53093c74-2100-4bf4-aac6-66d1973d03ef" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056" rel="self"/><link type="text/html" href="https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056" rel="alternate"/><thr:in-reply-to ref="tag:shitposter.club,2017-08-04:noticeId=4027863:objectType=comment" href="https://shitposter.club/notice/4027863"/><author><id>https://social.sakamoto.gq/users/eal</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://social.sakamoto.gq/users/eal</uri><poco:preferredUsername>eal</poco:preferredUsername><poco:displayName>坂本</poco:displayName><poco:note>(・ヮ・)</poco:note><name>eal</name><link rel="avatar" href="https://social.sakamoto.gq/media/7646c027-3614-4ee1-93f9-eea8f244a0d7/1A2EFE3153B9C9C3826DB511D043A26597C9F7178C8A4899FBBF808972D1659F.png"/></author><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://shitposter.club/user/5381"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.hjkos.com/users/hj"/></entry> -\ No newline at end of file diff --git a/test/fixtures/tesla_mock/sakamoto_eal_feed.atom b/test/fixtures/tesla_mock/sakamoto_eal_feed.atom @@ -1 +0,0 @@ -<?xml version="1.0"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0"><id>https://social.sakamoto.gq/users/eal/feed.atom</id><title>eal's timeline</title><updated>2017-08-04T14:19:12.683854</updated><link rel="hub" href="https://social.sakamoto.gq/push/hub/eal"/><link rel="salmon" href="https://social.sakamoto.gq/users/eal/salmon"/><link rel="self" href="https://social.sakamoto.gq/users/eal/feed.atom" type="application/atom+xml"/><author><id>https://social.sakamoto.gq/users/eal</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://social.sakamoto.gq/users/eal</uri><poco:preferredUsername>eal</poco:preferredUsername><poco:displayName>坂本</poco:displayName><poco:note>(・ヮ・)</poco:note><name>eal</name><link rel="avatar" href="https://social.sakamoto.gq/media/7646c027-3614-4ee1-93f9-eea8f244a0d7/1A2EFE3153B9C9C3826DB511D043A26597C9F7178C8A4899FBBF808972D1659F.png"/></author><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://social.sakamoto.gq/objects/b79a1721-23f3-45a5-9610-adb08c2afae5</id><title>New note by eal</title><content type="html">Honestly, I like all smileys that are not emoji.</content><published>2017-08-04T14:19:12.675999Z</published><updated>2017-08-04T14:19:12.675999Z</updated><ostatus:conversation>https://social.sakamoto.gq/contexts/e05ede92-8db9-4963-8b8e-e71a5797d68f</ostatus:conversation><link ref="https://social.sakamoto.gq/contexts/e05ede92-8db9-4963-8b8e-e71a5797d68f" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://social.sakamoto.gq/objects/b79a1721-23f3-45a5-9610-adb08c2afae5" rel="self"/><link type="text/html" href="https://social.sakamoto.gq/objects/b79a1721-23f3-45a5-9610-adb08c2afae5" rel="alternate"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://social.sakamoto.gq/objects/45475bf3-2dfc-4d9e-8eae-1f4f86f48982</id><title>New note by eal</title><content type="html">Then again, I like all smileys/emoticons that are not emoji.&lt;br&gt;</content><published>2017-08-04T14:19:10.113373Z</published><updated>2017-08-04T14:19:10.113373Z</updated><ostatus:conversation>https://social.sakamoto.gq/contexts/852d1605-4dcb-4ba7-9ba4-dfc37ed62fbc</ostatus:conversation><link ref="https://social.sakamoto.gq/contexts/852d1605-4dcb-4ba7-9ba4-dfc37ed62fbc" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://social.sakamoto.gq/objects/45475bf3-2dfc-4d9e-8eae-1f4f86f48982" rel="self"/><link type="text/html" href="https://social.sakamoto.gq/objects/45475bf3-2dfc-4d9e-8eae-1f4f86f48982" rel="alternate"/><thr:in-reply-to ref="https://social.sakamoto.gq/objects/8f8fd6d6-cc63-40c6-a5d0-1c0e4f919368" href="https://social.sakamoto.gq/objects/8f8fd6d6-cc63-40c6-a5d0-1c0e4f919368"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.sakamoto.gq/users/eal"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://social.sakamoto.gq/objects/8f8fd6d6-cc63-40c6-a5d0-1c0e4f919368</id><title>New note by eal</title><content type="html">I love the russian-style smiley.</content><published>2017-08-04T14:18:30.478552Z</published><updated>2017-08-04T14:18:30.478552Z</updated><ostatus:conversation>https://social.sakamoto.gq/contexts/852d1605-4dcb-4ba7-9ba4-dfc37ed62fbc</ostatus:conversation><link ref="https://social.sakamoto.gq/contexts/852d1605-4dcb-4ba7-9ba4-dfc37ed62fbc" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://social.sakamoto.gq/objects/8f8fd6d6-cc63-40c6-a5d0-1c0e4f919368" rel="self"/><link type="text/html" href="https://social.sakamoto.gq/objects/8f8fd6d6-cc63-40c6-a5d0-1c0e4f919368" rel="alternate"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/6e69df95-f2ad-4b8e-af4a-e93ff93d64e1</id><title>eal started following https://cybre.space/users/0x3F</title><content type="html">eal started following https://cybre.space/users/0x3F</content><published>2017-08-04T14:17:24.942193Z</published><updated>2017-08-04T14:17:24.942193Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://cybre.space/users/0x3F</id><uri>https://cybre.space/users/0x3F</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/6e69df95-f2ad-4b8e-af4a-e93ff93d64e1"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://cybre.space/users/0x3F"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/54c5e260-0185-4267-a2a6-f5dd9c76c2c9</id><title>eal started following https://niu.moe/users/rye</title><content type="html">eal started following https://niu.moe/users/rye</content><published>2017-08-04T14:16:35.604739Z</published><updated>2017-08-04T14:16:35.604739Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://niu.moe/users/rye</id><uri>https://niu.moe/users/rye</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/54c5e260-0185-4267-a2a6-f5dd9c76c2c9"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://niu.moe/users/rye"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/092ca863-19a8-416c-85d7-d3f23b3c0203</id><title>eal started following https://mastodon.xyz/users/rafudesu</title><content type="html">eal started following https://mastodon.xyz/users/rafudesu</content><published>2017-08-04T14:16:10.993429Z</published><updated>2017-08-04T14:16:10.993429Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://mastodon.xyz/users/rafudesu</id><uri>https://mastodon.xyz/users/rafudesu</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/092ca863-19a8-416c-85d7-d3f23b3c0203"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.xyz/users/rafudesu"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/be5cf702-b127-423b-a6be-5f78f01a4289</id><title>eal started following https://gs.kawa-kun.com/user/2</title><content type="html">eal started following https://gs.kawa-kun.com/user/2</content><published>2017-08-04T14:15:41.804611Z</published><updated>2017-08-04T14:15:41.804611Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://gs.kawa-kun.com/user/2</id><uri>https://gs.kawa-kun.com/user/2</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/be5cf702-b127-423b-a6be-5f78f01a4289"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.kawa-kun.com/user/2"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/4951e2a1-9bae-4e87-8e98-e6d2f8a52338</id><title>eal started following https://gs.kawa-kun.com/user/4885</title><content type="html">eal started following https://gs.kawa-kun.com/user/4885</content><published>2017-08-04T14:15:00.135352Z</published><updated>2017-08-04T14:15:00.135352Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://gs.kawa-kun.com/user/4885</id><uri>https://gs.kawa-kun.com/user/4885</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/4951e2a1-9bae-4e87-8e98-e6d2f8a52338"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.kawa-kun.com/user/4885"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/cadf8745-b9ee-4f6c-af32-bfddb70e4607</id><title>eal started following https://mastodon.social/users/Murassa</title><content type="html">eal started following https://mastodon.social/users/Murassa</content><published>2017-08-04T14:14:36.339560Z</published><updated>2017-08-04T14:14:36.339560Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://mastodon.social/users/Murassa</id><uri>https://mastodon.social/users/Murassa</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/cadf8745-b9ee-4f6c-af32-bfddb70e4607"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/Murassa"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/a52c9aab-f0e6-4ccb-8dd3-9f417e72a41c</id><title>eal started following https://mastodon.social/users/rysiek</title><content type="html">eal started following https://mastodon.social/users/rysiek</content><published>2017-08-04T14:13:04.061572Z</published><updated>2017-08-04T14:13:04.061572Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://mastodon.social/users/rysiek</id><uri>https://mastodon.social/users/rysiek</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/a52c9aab-f0e6-4ccb-8dd3-9f417e72a41c"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/rysiek"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/738bc887-4cca-4b36-8c86-2b54d4c54732</id><title>eal started following https://mastodon.hasameli.com/users/munin</title><content type="html">eal started following https://mastodon.hasameli.com/users/munin</content><published>2017-08-04T14:12:10.514155Z</published><updated>2017-08-04T14:12:10.514155Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://mastodon.hasameli.com/users/munin</id><uri>https://mastodon.hasameli.com/users/munin</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/738bc887-4cca-4b36-8c86-2b54d4c54732"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.hasameli.com/users/munin"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/dc66ad5a-b776-4180-a8aa-e4c1bf7cb703</id><title>eal started following https://cybre.space/users/nightpool</title><content type="html">eal started following https://cybre.space/users/nightpool</content><published>2017-08-04T14:11:16.046148Z</published><updated>2017-08-04T14:11:16.046148Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://cybre.space/users/nightpool</id><uri>https://cybre.space/users/nightpool</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/dc66ad5a-b776-4180-a8aa-e4c1bf7cb703"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://cybre.space/users/nightpool"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://social.sakamoto.gq/objects/9c5c00d7-3ce4-4c11-b965-dc5c2bda86c5</id><title>New note by eal</title><content type="html">&lt;a href='https://mastodon.zombocloud.com/users/staticsafe'&gt;@staticsafe&lt;/a&gt; privet )))</content><published>2017-08-04T14:10:08.812247Z</published><updated>2017-08-04T14:10:08.812247Z</updated><ostatus:conversation>https://social.sakamoto.gq/contexts/12a33823-0327-4c1c-a591-850ea79331b5</ostatus:conversation><link ref="https://social.sakamoto.gq/contexts/12a33823-0327-4c1c-a591-850ea79331b5" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://social.sakamoto.gq/objects/9c5c00d7-3ce4-4c11-b965-dc5c2bda86c5" rel="self"/><link type="text/html" href="https://social.sakamoto.gq/objects/9c5c00d7-3ce4-4c11-b965-dc5c2bda86c5" rel="alternate"/><thr:in-reply-to ref="tag:mastodon.zombocloud.com,2017-08-04:objectId=995766:objectType=Status" href="https://mastodon.zombocloud.com/users/staticsafe/updates/4900"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.zombocloud.com/users/staticsafe"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/49798053-1f40-4a71-ad33-106e90630863</id><title>eal started following https://social.homunyan.com/users/animeirl</title><content type="html">eal started following https://social.homunyan.com/users/animeirl</content><published>2017-08-04T14:09:44.904792Z</published><updated>2017-08-04T14:09:44.904792Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://social.homunyan.com/users/animeirl</id><uri>https://social.homunyan.com/users/animeirl</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/49798053-1f40-4a71-ad33-106e90630863"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.homunyan.com/users/animeirl"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://social.sakamoto.gq/activities/2d83a1c5-70a6-45d3-9b84-59d6a70fbb17</id><title>New favorite by eal</title><content type="html">eal favorited something</content><published>2017-08-04T14:07:27.210044Z</published><updated>2017-08-04T14:07:27.210044Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>https://pleroma.soykaf.com/objects/b831e52f-4ed4-438e-95b4-888897f64f09</id></activity:object><ostatus:conversation>https://pleroma.hjkos.com/contexts/3ed48205-1e72-4e19-a618-89a0d2ca811e</ostatus:conversation><link ref="https://pleroma.hjkos.com/contexts/3ed48205-1e72-4e19-a618-89a0d2ca811e" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/2d83a1c5-70a6-45d3-9b84-59d6a70fbb17"/><thr:in-reply-to ref="https://pleroma.soykaf.com/objects/b831e52f-4ed4-438e-95b4-888897f64f09"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://social.sakamoto.gq/activities/06d28bed-544a-496b-8414-1c6d439273b5</id><title>New favorite by eal</title><content type="html">eal favorited something</content><published>2017-08-04T14:05:37.280200Z</published><updated>2017-08-04T14:05:37.280200Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:toot-lab.reclaim.technology,2017-08-04:objectId=1166030:objectType=Status</id></activity:object><ostatus:conversation>tag:p2px.me,2017-08-04:objectType=thread:nonce=f8bfc4d13db6ce91</ostatus:conversation><link ref="tag:p2px.me,2017-08-04:objectType=thread:nonce=f8bfc4d13db6ce91" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/06d28bed-544a-496b-8414-1c6d439273b5"/><thr:in-reply-to ref="tag:toot-lab.reclaim.technology,2017-08-04:objectId=1166030:objectType=Status"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://toot-lab.reclaim.technology/users/djsundog"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/72bf19d4-9ad4-4b2f-9cd0-f0d70f4e931b</id><title>eal started following https://mstdn.jp/users/nullkal</title><content type="html">eal started following https://mstdn.jp/users/nullkal</content><published>2017-08-04T14:05:04.148904Z</published><updated>2017-08-04T14:05:04.148904Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://mstdn.jp/users/nullkal</id><uri>https://mstdn.jp/users/nullkal</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/72bf19d4-9ad4-4b2f-9cd0-f0d70f4e931b"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mstdn.jp/users/nullkal"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://social.sakamoto.gq/objects/b0e89515-7621-4e09-b23d-83e192324107</id><title>New note by eal</title><content type="html">&lt;a href='https://p2px.me/user/1'&gt;@stitchxd&lt;/a&gt; test also</content><published>2017-08-04T14:04:38.699051Z</published><updated>2017-08-04T14:04:38.699051Z</updated><ostatus:conversation>tag:p2px.me,2017-08-04:objectType=thread:nonce=f8bfc4d13db6ce91</ostatus:conversation><link ref="tag:p2px.me,2017-08-04:objectType=thread:nonce=f8bfc4d13db6ce91" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://social.sakamoto.gq/objects/b0e89515-7621-4e09-b23d-83e192324107" rel="self"/><link type="text/html" href="https://social.sakamoto.gq/objects/b0e89515-7621-4e09-b23d-83e192324107" rel="alternate"/><thr:in-reply-to ref="tag:p2px.me,2017-08-04:noticeId=222109:objectType=note" href="https://p2px.me/notice/222109"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://p2px.me/user/1"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://social.sakamoto.gq/activities/d8d2006b-6b23-45d6-ba27-39d27587777d</id><title>New favorite by eal</title><content type="html">eal favorited something</content><published>2017-08-04T14:04:32.106626Z</published><updated>2017-08-04T14:04:32.106626Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:p2px.me,2017-08-04:noticeId=222109:objectType=note</id></activity:object><ostatus:conversation>tag:p2px.me,2017-08-04:objectType=thread:nonce=f8bfc4d13db6ce91</ostatus:conversation><link ref="tag:p2px.me,2017-08-04:objectType=thread:nonce=f8bfc4d13db6ce91" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/d8d2006b-6b23-45d6-ba27-39d27587777d"/><thr:in-reply-to ref="tag:p2px.me,2017-08-04:noticeId=222109:objectType=note"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://p2px.me/user/1"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://social.sakamoto.gq/activities/cb9db95d-ec27-41fa-bebd-5375fc13acb9</id><title>eal started following https://mastodon.social/users/Gargron</title><content type="html">eal started following https://mastodon.social/users/Gargron</content><published>2017-08-04T14:04:04.325531Z</published><updated>2017-08-04T14:04:04.325531Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://mastodon.social/users/Gargron</id><uri>https://mastodon.social/users/Gargron</uri></activity:object><link rel="self" type="application/atom+xml" href="https://social.sakamoto.gq/activities/cb9db95d-ec27-41fa-bebd-5375fc13acb9"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.social/users/Gargron"/></entry></feed> -\ No newline at end of file diff --git a/test/fixtures/tesla_mock/shp@pleroma.soykaf.com.feed b/test/fixtures/tesla_mock/shp@pleroma.soykaf.com.feed @@ -1 +0,0 @@ -<?xml version="1.0"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0"><id>https://pleroma.soykaf.com/users/shp/feed.atom</id><title>shp's timeline</title><updated>2017-09-14T08:31:48.911686</updated><link rel="hub" href="https://pleroma.soykaf.com/push/hub/shp"/><link rel="salmon" href="https://pleroma.soykaf.com/users/shp/salmon"/><link rel="self" href="https://pleroma.soykaf.com/users/shp/feed.atom" type="application/atom+xml"/><author><id>https://pleroma.soykaf.com/users/shp</id><activity:object>http://activitystrea.ms/schema/1.0/person</activity:object><uri>https://pleroma.soykaf.com/users/shp</uri><poco:preferredUsername>shp</poco:preferredUsername><poco:displayName>shp</poco:displayName><poco:note>cofe</poco:note><name>shp</name><link rel="avatar" href="https://pleroma.soykaf.com/media/745e4713-008c-4f54-bc26-4f59c37cea0e/43B7A3B2F0B9C0AA097F1B01E9EF05F7C1DCFA6868566D8A9AC211E483498643.png"/></author><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://pleroma.soykaf.com/activities/0b5f5ef2-020a-4f9e-a92b-a2bf21224644</id><title>shp started following https://pleroma.soykaf.com/users/gooz</title><content type="html">shp started following https://pleroma.soykaf.com/users/gooz</content><published>2017-09-14T08:31:48.911226Z</published><updated>2017-09-14T08:31:48.911226Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://pleroma.soykaf.com/users/gooz</id><uri>https://pleroma.soykaf.com/users/gooz</uri></activity:object><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/0b5f5ef2-020a-4f9e-a92b-a2bf21224644"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/gooz"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb><id>https://pleroma.soykaf.com/activities/d928b7f7-dc10-478c-859b-cd604770da60</id><title>shp started following https://niu.moe/users/xiaoyongmao</title><content type="html">shp started following https://niu.moe/users/xiaoyongmao</content><published>2017-09-14T08:16:52.674253Z</published><updated>2017-09-14T08:16:52.674253Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type><id>https://niu.moe/users/xiaoyongmao</id><uri>https://niu.moe/users/xiaoyongmao</uri></activity:object><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/d928b7f7-dc10-478c-859b-cd604770da60"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://niu.moe/users/xiaoyongmao"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/3f5089b3-f1e5-47b6-8bfe-a9c4a860e724</id><title>New favorite by shp</title><content type="html">shp favorited something</content><published>2017-09-14T08:12:18.213055Z</published><updated>2017-09-14T08:12:18.213055Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>https://mastodon.xyz/users/Azurolu/statuses/8346804</id></activity:object><ostatus:conversation ref="tag:mastodon.xyz,2017-09-14:objectId=3669709:objectType=Conversation">tag:mastodon.xyz,2017-09-14:objectId=3669709:objectType=Conversation</ostatus:conversation><link ref="tag:mastodon.xyz,2017-09-14:objectId=3669709:objectType=Conversation" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/3f5089b3-f1e5-47b6-8bfe-a9c4a860e724"/><thr:in-reply-to ref="https://mastodon.xyz/users/Azurolu/statuses/8346804"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mastodon.xyz/users/Azurolu"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/0def9b19-6b0f-44e0-96b3-543fa06a4010</id><title>New note by shp</title><content type="html">&lt;a href='https://niu.moe/users/Pasty'&gt;@Pasty&lt;/a&gt; I love the peach&lt;br&gt;&lt;a href="https://pleroma.soykaf.com/media/7e8bd209-dbd4-481a-a62c-d302d68df16d/__hinanawi_tenshi_touhou_drawn_by_e_o__8c6824f52dd494f6026607570179265f.jpg" class='attachment'&gt;__hinanawi_tenshi_touhou_drawn_…&lt;/a&gt;</content><published>2017-09-14T08:12:04.367142Z</published><updated>2017-09-14T08:12:04.367142Z</updated><ostatus:conversation ref="tag:niu.moe,2017-09-14:objectId=1660781:objectType=Conversation">tag:niu.moe,2017-09-14:objectId=1660781:objectType=Conversation</ostatus:conversation><link ref="tag:niu.moe,2017-09-14:objectId=1660781:objectType=Conversation" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/0def9b19-6b0f-44e0-96b3-543fa06a4010" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/0def9b19-6b0f-44e0-96b3-543fa06a4010" rel="alternate"/><link rel="enclosure" href="https://pleroma.soykaf.com/media/7e8bd209-dbd4-481a-a62c-d302d68df16d/__hinanawi_tenshi_touhou_drawn_by_e_o__8c6824f52dd494f6026607570179265f.jpg" type="image/jpeg"/><thr:in-reply-to ref="https://niu.moe/users/Pasty/statuses/3211030" href="https://niu.moe/@Pasty/3211030"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://niu.moe/users/Pasty"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/a4170edf-d273-4b82-931d-662aaf3872f3</id><title>New favorite by shp</title><content type="html">shp favorited something</content><published>2017-09-14T08:10:26.205104Z</published><updated>2017-09-14T08:10:26.205104Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>https://niu.moe/users/NekoiNemo/statuses/3210992</id></activity:object><ostatus:conversation ref="tag:niu.moe,2017-09-14:objectId=1660761:objectType=Conversation">tag:niu.moe,2017-09-14:objectId=1660761:objectType=Conversation</ostatus:conversation><link ref="tag:niu.moe,2017-09-14:objectId=1660761:objectType=Conversation" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/a4170edf-d273-4b82-931d-662aaf3872f3"/><thr:in-reply-to ref="https://niu.moe/users/NekoiNemo/statuses/3210992"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://niu.moe/users/NekoiNemo"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/c50c47a0-fac5-4781-a7e6-f20e7226d5fc</id><title>New note by shp</title><content type="html">&lt;a href='https://freezepeach.xyz/user/3458'&gt;@hakui&lt;/a&gt; &lt;a href='https://pleroma.soykaf.com/users/lain'&gt;@lain&lt;/a&gt; you guys are forgetting the pancakes jeez</content><published>2017-09-14T08:09:30.088418Z</published><updated>2017-09-14T08:09:30.088418Z</updated><ostatus:conversation ref="https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623">https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623</ostatus:conversation><link ref="https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/c50c47a0-fac5-4781-a7e6-f20e7226d5fc" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/c50c47a0-fac5-4781-a7e6-f20e7226d5fc" rel="alternate"/><thr:in-reply-to ref="tag:freezepeach.xyz,2017-09-14:noticeId=3926191:objectType=comment" href="https://freezepeach.xyz/notice/3926191"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/2af9f622-5986-483c-83a1-ac59a9035b50</id><title>New favorite by shp</title><content type="html">shp favorited something</content><published>2017-09-14T08:09:16.346235Z</published><updated>2017-09-14T08:09:16.346235Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:freezepeach.xyz,2017-09-14:noticeId=3926191:objectType=comment</id></activity:object><ostatus:conversation ref="https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623">https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623</ostatus:conversation><link ref="https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/2af9f622-5986-483c-83a1-ac59a9035b50"/><thr:in-reply-to ref="tag:freezepeach.xyz,2017-09-14:noticeId=3926191:objectType=comment"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/f52aad69-5828-4e0e-bb7b-f2f0869d3ff0</id><title>New note by shp</title><content type="html">&lt;a href='https://gs.smuglo.li/user/253'&gt;@kro&lt;/a&gt; I'll probs try some of those 2hu mangos</content><published>2017-09-14T08:09:13.262835Z</published><updated>2017-09-14T08:09:13.262835Z</updated><ostatus:conversation ref="tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123">tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123</ostatus:conversation><link ref="tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/f52aad69-5828-4e0e-bb7b-f2f0869d3ff0" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/f52aad69-5828-4e0e-bb7b-f2f0869d3ff0" rel="alternate"/><thr:in-reply-to ref="tag:gs.smuglo.li,2017-09-14:noticeId=4113226:objectType=comment" href="https://gs.smuglo.li/notice/4113226"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/253"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/35743658-efee-46cf-9cdf-487b95709cd5</id><title>New favorite by shp</title><content type="html">shp favorited something</content><published>2017-09-14T08:09:00.517534Z</published><updated>2017-09-14T08:09:00.517534Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:gs.smuglo.li,2017-09-14:noticeId=4113226:objectType=comment</id></activity:object><ostatus:conversation ref="tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123">tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123</ostatus:conversation><link ref="tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/35743658-efee-46cf-9cdf-487b95709cd5"/><thr:in-reply-to ref="tag:gs.smuglo.li,2017-09-14:noticeId=4113226:objectType=comment"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/253"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/22258ba8-58dc-4e09-b476-fe28d3307377</id><title>New favorite by shp</title><content type="html">shp favorited something</content><published>2017-09-14T08:08:38.087136Z</published><updated>2017-09-14T08:08:38.087136Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>https://pleroma.soykaf.com/objects/13d7809e-5dca-4117-8738-887759392f2c</id></activity:object><ostatus:conversation ref="https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623">https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623</ostatus:conversation><link ref="https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/22258ba8-58dc-4e09-b476-fe28d3307377"/><thr:in-reply-to ref="https://pleroma.soykaf.com/objects/13d7809e-5dca-4117-8738-887759392f2c"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/f56d640a-0dbd-48af-80b1-06d0dbd26774</id><title>New note by shp</title><content type="html">&lt;a href='https://social.sakamoto.gq/users/eal'&gt;@eal&lt;/a&gt; ...but neither does my phone&lt;br&gt;&lt;br&gt;low brightness, very dark wallpaper (pic related, but even darker, couldn't find the actual version)&lt;br&gt;&lt;a href="https://pleroma.soykaf.com/media/6d1b8d57-80ae-41d6-bdea-58fea09ecdf4/phonewallpaper.png" class='attachment'&gt;phonewallpaper.png&lt;/a&gt;</content><published>2017-09-14T08:07:23.081214Z</published><updated>2017-09-14T08:07:23.081214Z</updated><ostatus:conversation ref="https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355">https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355</ostatus:conversation><link ref="https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/f56d640a-0dbd-48af-80b1-06d0dbd26774" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/f56d640a-0dbd-48af-80b1-06d0dbd26774" rel="alternate"/><link rel="enclosure" href="https://pleroma.soykaf.com/media/6d1b8d57-80ae-41d6-bdea-58fea09ecdf4/phonewallpaper.png" type="image/png"/><thr:in-reply-to ref="https://social.sakamoto.gq/objects/3fa38f35-47ef-4286-ad22-c953643f0bbb" href="https://social.sakamoto.gq/objects/3fa38f35-47ef-4286-ad22-c953643f0bbb"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.sakamoto.gq/users/eal"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/d313df1d-121c-4ab8-abd1-e6aedcf55cbd</id><title>New note by shp</title><content type="html">&lt;a href='https://niu.moe/users/Pasty'&gt;@Pasty&lt;/a&gt; y-you too</content><published>2017-09-14T07:55:26.153486Z</published><updated>2017-09-14T07:55:26.153486Z</updated><ostatus:conversation ref="tag:niu.moe,2017-09-14:objectId=1660616:objectType=Conversation">tag:niu.moe,2017-09-14:objectId=1660616:objectType=Conversation</ostatus:conversation><link ref="tag:niu.moe,2017-09-14:objectId=1660616:objectType=Conversation" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/d313df1d-121c-4ab8-abd1-e6aedcf55cbd" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/d313df1d-121c-4ab8-abd1-e6aedcf55cbd" rel="alternate"/><thr:in-reply-to ref="https://niu.moe/users/Pasty/statuses/3210773" href="https://niu.moe/@Pasty/3210773"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://niu.moe/users/Pasty"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/7b642424-4edb-48cc-8711-1eafb4745269</id><title>New note by shp</title><content type="html">&lt;a href='https://social.sakamoto.gq/users/eal'&gt;@eal&lt;/a&gt; bothers me more when sleeping, wore one for nearly 2 years</content><published>2017-09-14T07:54:53.449227Z</published><updated>2017-09-14T07:54:53.449227Z</updated><ostatus:conversation ref="https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355">https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355</ostatus:conversation><link ref="https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/7b642424-4edb-48cc-8711-1eafb4745269" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/7b642424-4edb-48cc-8711-1eafb4745269" rel="alternate"/><thr:in-reply-to ref="https://social.sakamoto.gq/objects/ac9e8340-5427-44d3-b29e-ef006133daaa" href="https://social.sakamoto.gq/objects/ac9e8340-5427-44d3-b29e-ef006133daaa"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://social.sakamoto.gq/users/eal"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/5bc1bff1-88c3-489d-8efd-7e4755690a18</id><title>New note by shp</title><content type="html">quick test</content><published>2017-09-14T07:54:09.045525Z</published><updated>2017-09-14T07:54:09.045525Z</updated><ostatus:conversation ref="https://pleroma.soykaf.com/contexts/cd770c2a-408e-4895-988c-60319298f219">https://pleroma.soykaf.com/contexts/cd770c2a-408e-4895-988c-60319298f219</ostatus:conversation><link ref="https://pleroma.soykaf.com/contexts/cd770c2a-408e-4895-988c-60319298f219" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/5bc1bff1-88c3-489d-8efd-7e4755690a18" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/5bc1bff1-88c3-489d-8efd-7e4755690a18" rel="alternate"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/956f1fb5-6f2f-433e-ab71-7f732b76f4be</id><title>New note by shp</title><content type="html">had some trouble getting sleep last night. only used phone to check the time a few times (v essential to have a near-black wallpaper to not blind yourself when you do that). can't rember the last time I rolled in the bed for longer than an hour like that</content><published>2017-09-14T07:51:23.557775Z</published><updated>2017-09-14T07:51:23.557775Z</updated><ostatus:conversation ref="https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355">https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355</ostatus:conversation><link ref="https://pleroma.soykaf.com/contexts/f4c5d56e-fc58-467b-a8a5-10515c012355" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/956f1fb5-6f2f-433e-ab71-7f732b76f4be" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/956f1fb5-6f2f-433e-ab71-7f732b76f4be" rel="alternate"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/d935d9f2-ebc7-4ff2-b65a-fbf418a60935</id><title>New note by shp</title><content type="html">&lt;a href='https://gs.smuglo.li/user/253'&gt;@kro&lt;/a&gt; doesn't sound like a bad idea at all</content><published>2017-09-14T07:49:55.702555Z</published><updated>2017-09-14T07:49:55.702555Z</updated><ostatus:conversation ref="tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123">tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123</ostatus:conversation><link ref="tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/d935d9f2-ebc7-4ff2-b65a-fbf418a60935" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/d935d9f2-ebc7-4ff2-b65a-fbf418a60935" rel="alternate"/><thr:in-reply-to ref="tag:gs.smuglo.li,2017-09-14:noticeId=4113170:objectType=comment" href="https://gs.smuglo.li/notice/4113170"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/253"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/342c8803-ee16-487d-9488-a39d763073f6</id><title>New favorite by shp</title><content type="html">shp favorited something</content><published>2017-09-14T07:49:41.875840Z</published><updated>2017-09-14T07:49:41.875840Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:anticapitalist.party,2017-09-14:objectId=3322865:objectType=Status</id></activity:object><ostatus:conversation ref="tag:anticapitalist.party,2017-09-14:objectId=1251751:objectType=Conversation">tag:anticapitalist.party,2017-09-14:objectId=1251751:objectType=Conversation</ostatus:conversation><link ref="tag:anticapitalist.party,2017-09-14:objectId=1251751:objectType=Conversation" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/342c8803-ee16-487d-9488-a39d763073f6"/><thr:in-reply-to ref="tag:anticapitalist.party,2017-09-14:objectId=3322865:objectType=Status"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://anticapitalist.party/users/Concerned_Commy"/></entry><entry><activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb><id>https://pleroma.soykaf.com/activities/5d98a19b-dd55-4077-9841-142937c613ad</id><title>New favorite by shp</title><content type="html">shp favorited something</content><published>2017-09-14T07:49:30.584265Z</published><updated>2017-09-14T07:49:30.584265Z</updated><activity:object><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><id>tag:gs.smuglo.li,2017-09-14:noticeId=4113170:objectType=comment</id></activity:object><ostatus:conversation ref="tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123">tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123</ostatus:conversation><link ref="tag:gs.smuglo.li,2017-09-14:objectType=thread:nonce=c4ac2016e07c4123" rel="ostatus:conversation"/><link rel="self" type="application/atom+xml" href="https://pleroma.soykaf.com/activities/5d98a19b-dd55-4077-9841-142937c613ad"/><thr:in-reply-to ref="tag:gs.smuglo.li,2017-09-14:noticeId=4113170:objectType=comment"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/253"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/fdf3626a-50ba-458b-9bf7-b5f2cfa505fc</id><title>New note by shp</title><content type="html">&lt;a href='https://pleroma.hjkos.com/users/hj'&gt;@hj&lt;/a&gt; c time</content><published>2017-09-14T07:48:52.805422Z</published><updated>2017-09-14T07:48:52.805422Z</updated><ostatus:conversation ref="https://pleroma.hjkos.com/contexts/dc4a3a3e-d366-4c0c-8789-8a9bee3537d9">https://pleroma.hjkos.com/contexts/dc4a3a3e-d366-4c0c-8789-8a9bee3537d9</ostatus:conversation><link ref="https://pleroma.hjkos.com/contexts/dc4a3a3e-d366-4c0c-8789-8a9bee3537d9" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/fdf3626a-50ba-458b-9bf7-b5f2cfa505fc" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/fdf3626a-50ba-458b-9bf7-b5f2cfa505fc" rel="alternate"/><thr:in-reply-to ref="https://pleroma.hjkos.com/objects/581c2769-8981-43d1-b47b-815aa1282c26" href="https://pleroma.hjkos.com/objects/581c2769-8981-43d1-b47b-815aa1282c26"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.hjkos.com/users/hj"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/></entry><entry><activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type><activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb><id>https://pleroma.soykaf.com/objects/c7c8eb17-b669-4827-9fbc-90f1fc54e4b1</id><title>New note by shp</title><content type="html">&lt;a href='https://sunshinegardens.org/users/tbny'&gt;@tbny&lt;/a&gt; err.. mediterranean from finnish*</content><published>2017-09-14T07:46:52.764234Z</published><updated>2017-09-14T07:46:52.764234Z</updated><ostatus:conversation ref="https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623">https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623</ostatus:conversation><link ref="https://pleroma.soykaf.com/contexts/ac9c98ee-3eca-4b4b-9620-64b5e85e2623" rel="ostatus:conversation"/><link type="application/atom+xml" href="https://pleroma.soykaf.com/objects/c7c8eb17-b669-4827-9fbc-90f1fc54e4b1" rel="self"/><link type="text/html" href="https://pleroma.soykaf.com/objects/c7c8eb17-b669-4827-9fbc-90f1fc54e4b1" rel="alternate"/><thr:in-reply-to ref="https://pleroma.soykaf.com/objects/15ea896c-c943-4b65-8f31-d6cda91a52fd" href="https://pleroma.soykaf.com/objects/15ea896c-c943-4b65-8f31-d6cda91a52fd"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/shp"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/><link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://sunshinegardens.org/users/tbny"/></entry></feed> -\ No newline at end of file diff --git a/test/fixtures/tesla_mock/spc_5381.atom b/test/fixtures/tesla_mock/spc_5381.atom @@ -1,438 +0,0 @@ -<?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-beta4">GNU social</generator> - <id>https://shitposter.club/api/statuses/user_timeline/5381.atom</id> - <title>shpuld timeline</title> - <subtitle>Updates from shpuld on Shitposter Club!</subtitle> - <logo>https://shitposter.club/avatar/5381-96-20171230093854.png</logo> - <updated>2018-02-23T13:42:22+00:00</updated> -<author> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <uri>https://shitposter.club/user/5381</uri> - <name>shpuld</name> - <link rel="alternate" type="text/html" href="https://shitposter.club/shpuld"/> - <link rel="avatar" type="image/png" media:width="864" media:height="864" href="https://shitposter.club/avatar/5381-original-20171230093854.png"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="https://shitposter.club/avatar/5381-96-20171230093854.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="https://shitposter.club/avatar/5381-48-20171230093854.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="https://shitposter.club/avatar/5381-24-20171230093900.png"/> - <poco:preferredUsername>shpuld</poco:preferredUsername> - <poco:displayName>shp</poco:displayName> - <followers url="https://shitposter.club/shpuld/subscribers"></followers> - <statusnet:profile_info local_id="5381"></statusnet:profile_info> -</author> - <link href="https://shitposter.club/shpuld" rel="alternate" type="text/html"/> - <link href="https://shitposter.club/main/sup" rel="http://api.friendfeed.com/2008/03#sup" type="application/json"/> - <link href="https://shitposter.club/api/statuses/user_timeline/5381.atom?max_id=7387342" rel="next" type="application/atom+xml"/> - <link href="https://shitposter.club/main/push/hub" rel="hub"/> - <link href="https://shitposter.club/main/salmon/user/5381" rel="salmon"/> - <link href="https://shitposter.club/main/salmon/user/5381" rel="http://salmon-protocol.org/ns/salmon-replies"/> - <link href="https://shitposter.club/main/salmon/user/5381" rel="http://salmon-protocol.org/ns/salmon-mention"/> - <link href="https://shitposter.club/api/statuses/user_timeline/5381.atom" rel="self" type="application/atom+xml"/> -<entry> - <id>tag:shitposter.club,2018-02-23:fave:5381:comment:7387801:2018-02-23T13:39:40+00:00</id> - <title>Favorite</title> - <content type="html">shpuld favorited something by mayuutann: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://freezepeach.xyz/hakui&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;hakui&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://gs.smuglo.li/histoire&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;histoire&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://shitposter.club/shpuld&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;shpuld&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;a href=&quot;https://mstdn.io/media/_Ee-x91XN0udpfZVO_U&quot; rel=&quot;nofollow&quot;&gt;&lt;span class=&quot;invisible&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;ellipsis&quot;&gt;mstdn.io/media/_Ee-x91XN0udpfZ&lt;/span&gt;&lt;span class=&quot;invisible&quot;&gt;VO_U&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387804"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2018-02-23T13:39:40+00:00</published> - <updated>2018-02-23T13:39:40+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>https://mstdn.io/users/mayuutann/statuses/99574950785668071</id> - <title>New comment by mayuutann</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://freezepeach.xyz/hakui&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;hakui&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://gs.smuglo.li/histoire&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;histoire&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://shitposter.club/shpuld&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;shpuld&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;a href=&quot;https://mstdn.io/media/_Ee-x91XN0udpfZVO_U&quot; rel=&quot;nofollow&quot;&gt;&lt;span class=&quot;invisible&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;ellipsis&quot;&gt;mstdn.io/media/_Ee-x91XN0udpfZ&lt;/span&gt;&lt;span class=&quot;invisible&quot;&gt;VO_U&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mstdn.io/@mayuutann/99574950785668071"/> - <status_net notice_id="7387801"></status_net> - </activity:object> - <thr:in-reply-to ref="https://mstdn.io/users/mayuutann/statuses/99574950785668071" href="https://mstdn.io/@mayuutann/99574950785668071"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/@mayuutann/99574950785668071"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4389848"/> - <ostatus:conversation href="https://shitposter.club/conversation/4389848" local_id="4389848" ref="https://freezepeach.xyz/conversation/4182511">https://freezepeach.xyz/conversation/4182511</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://shitposter.club/api/statuses/show/7387804.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387804.atom"/> - <statusnet:notice_info local_id="7387804" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387723:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; @&lt;a href=&quot;https://pleroma.soykaf.com/users/lain&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x2468; lain &amp;#x2468;&quot;&gt;lain&lt;/a&gt; how naive~</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387723"/> - <status_net notice_id="7387723"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:30:15+00:00</published> - <updated>2018-02-23T13:30:15+00:00</updated> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451587:objectType=comment" href="https://freezepeach.xyz/notice/6451587"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451587"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4389967"/> - <ostatus:conversation href="https://shitposter.club/conversation/4389967" local_id="4389967" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=2f09acf104aebfe3">tag:shitposter.club,2018-02-23:objectType=thread:nonce=2f09acf104aebfe3</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <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://shitposter.club/api/statuses/show/7387723.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387723.atom"/> - <statusnet:notice_info local_id="7387723" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387703:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; @&lt;a href=&quot;https://pleroma.soykaf.com/users/lain&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x2468; lain &amp;#x2468;&quot;&gt;lain&lt;/a&gt; you expect anyone to believe that??</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387703"/> - <status_net notice_id="7387703"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:28:08+00:00</published> - <updated>2018-02-23T13:28:08+00:00</updated> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451569:objectType=comment" href="https://freezepeach.xyz/notice/6451569"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451569"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4389967"/> - <ostatus:conversation href="https://shitposter.club/conversation/4389967" local_id="4389967" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=2f09acf104aebfe3">tag:shitposter.club,2018-02-23:objectType=thread:nonce=2f09acf104aebfe3</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://pleroma.soykaf.com/users/lain"/> - <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://shitposter.club/api/statuses/show/7387703.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387703.atom"/> - <statusnet:notice_info local_id="7387703" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387639:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://mstdn.io/users/mayuutann&quot; class=&quot;h-card mention&quot; title=&quot;Mayutan&amp;#x2615;&quot;&gt;mayuutann&lt;/a&gt; @&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; pacyuri!! &lt;a href=&quot;https://shitposter.club/file/eea140be45df3f993c4533026bf9a78fe8facd296d2fa0c6d02b2e347c5dc30e.jpg&quot; title=&quot;https://shitposter.club/file/eea140be45df3f993c4533026bf9a78fe8facd296d2fa0c6d02b2e347c5dc30e.jpg&quot; class=&quot;attachment&quot; id=&quot;attachment-1589462&quot; rel=&quot;nofollow external&quot;&gt;https://shitposter.club/attachment/1589462&lt;/a&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387639"/> - <status_net notice_id="7387639"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:20:38+00:00</published> - <updated>2018-02-23T13:20:38+00:00</updated> - <thr:in-reply-to ref="https://mstdn.io/users/mayuutann/statuses/99574870416888767" href="https://mstdn.io/@mayuutann/99574870416888767"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/@mayuutann/99574870416888767"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390261"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390261" local_id="4390261" ref="https://freezepeach.xyz/conversation/4183220">https://freezepeach.xyz/conversation/4183220</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mstdn.io/users/mayuutann"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> - <link rel="enclosure" href="https://shitposter.club/file/eea140be45df3f993c4533026bf9a78fe8facd296d2fa0c6d02b2e347c5dc30e.jpg" type="image/jpeg" length="42186"/> - <link rel="self" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387639.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387639.atom"/> - <statusnet:notice_info local_id="7387639" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387611:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; why is pacyu eating a pizza so cute</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387611"/> - <status_net notice_id="7387611"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:18:07+00:00</published> - <updated>2018-02-23T13:18:07+00:00</updated> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451402:objectType=comment" href="https://freezepeach.xyz/notice/6451402"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451402"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390261"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390261" local_id="4390261" ref="https://freezepeach.xyz/conversation/4183220">https://freezepeach.xyz/conversation/4183220</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <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://shitposter.club/api/statuses/show/7387611.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387611.atom"/> - <statusnet:notice_info local_id="7387611" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <id>tag:shitposter.club,2018-02-23:fave:5381:comment:7387600:2018-02-23T13:17:52+00:00</id> - <title>Favorite</title> - <content type="html">shpuld favorited something by mayuutann: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://shitposter.club/shpuld&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;shpuld&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://gs.smuglo.li/histoire&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;histoire&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://freezepeach.xyz/hakui&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;hakui&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; pichu! &lt;a href=&quot;https://mstdn.io/media/Crv5eubz1KO0dgBEulI&quot; rel=&quot;nofollow&quot;&gt;&lt;span class=&quot;invisible&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;ellipsis&quot;&gt;mstdn.io/media/Crv5eubz1KO0dgB&lt;/span&gt;&lt;span class=&quot;invisible&quot;&gt;EulI&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387606"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2018-02-23T13:17:52+00:00</published> - <updated>2018-02-23T13:17:52+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>https://mstdn.io/users/mayuutann/statuses/99574863865459283</id> - <title>New comment by mayuutann</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://shitposter.club/shpuld&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;shpuld&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://gs.smuglo.li/histoire&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;histoire&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; &lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://freezepeach.xyz/hakui&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;hakui&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; pichu! &lt;a href=&quot;https://mstdn.io/media/Crv5eubz1KO0dgBEulI&quot; rel=&quot;nofollow&quot;&gt;&lt;span class=&quot;invisible&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;ellipsis&quot;&gt;mstdn.io/media/Crv5eubz1KO0dgB&lt;/span&gt;&lt;span class=&quot;invisible&quot;&gt;EulI&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mstdn.io/@mayuutann/99574863865459283"/> - <status_net notice_id="7387600"></status_net> - </activity:object> - <thr:in-reply-to ref="https://mstdn.io/users/mayuutann/statuses/99574863865459283" href="https://mstdn.io/@mayuutann/99574863865459283"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/@mayuutann/99574863865459283"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4389848"/> - <ostatus:conversation href="https://shitposter.club/conversation/4389848" local_id="4389848" ref="https://freezepeach.xyz/conversation/4182511">https://freezepeach.xyz/conversation/4182511</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://shitposter.club/api/statuses/show/7387606.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387606.atom"/> - <statusnet:notice_info local_id="7387606" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <id>tag:shitposter.club,2018-02-23:fave:5381:comment:7387544:2018-02-23T13:12:43+00:00</id> - <title>Favorite</title> - <content type="html">shpuld favorited something by mayuutann: &lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://shitposter.club/shpuld&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;shpuld&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; wa~~i!! :blobcheer:&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387557"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2018-02-23T13:12:43+00:00</published> - <updated>2018-02-23T13:12:43+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>https://mstdn.io/users/mayuutann/statuses/99574840290947233</id> - <title>New comment by mayuutann</title> - <content type="html">&lt;p&gt;&lt;span class=&quot;h-card&quot;&gt;&lt;a href=&quot;https://shitposter.club/shpuld&quot; class=&quot;u-url mention&quot;&gt;@&lt;span&gt;shpuld&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; wa~~i!! :blobcheer:&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mstdn.io/@mayuutann/99574840290947233"/> - <status_net notice_id="7387544"></status_net> - </activity:object> - <thr:in-reply-to ref="https://mstdn.io/users/mayuutann/statuses/99574840290947233" href="https://mstdn.io/@mayuutann/99574840290947233"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/@mayuutann/99574840290947233"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390030"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390030" local_id="4390030" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=d05e2b056274c5ab">tag:shitposter.club,2018-02-23:objectType=thread:nonce=d05e2b056274c5ab</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://shitposter.club/api/statuses/show/7387557.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387557.atom"/> - <statusnet:notice_info local_id="7387557" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387555:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; more!!</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387555"/> - <status_net notice_id="7387555"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:12:23+00:00</published> - <updated>2018-02-23T13:12:23+00:00</updated> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451332:objectType=note" href="https://freezepeach.xyz/notice/6451332"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451332"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390261"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390261" local_id="4390261" ref="https://freezepeach.xyz/conversation/4183220">https://freezepeach.xyz/conversation/4183220</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <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://shitposter.club/api/statuses/show/7387555.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387555.atom"/> - <statusnet:notice_info local_id="7387555" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <id>tag:shitposter.club,2018-02-23:fave:5381:note:7387537:2018-02-23T13:12:19+00:00</id> - <title>Favorite</title> - <content type="html">shpuld favorited something by hakui: you have pacyupacyu'd for: 45 minutes 03 seconds</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387553"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2018-02-23T13:12:19+00:00</published> - <updated>2018-02-23T13:12:19+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:freezepeach.xyz,2018-02-23:noticeId=6451332:objectType=note</id> - <title>New note by hakui</title> - <content type="html">you have pacyupacyu'd for: 45 minutes 03 seconds</content> - <link rel="alternate" type="text/html" href="https://freezepeach.xyz/notice/6451332"/> - <status_net notice_id="7387537"></status_net> - </activity:object> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451332:objectType=note" href="https://freezepeach.xyz/notice/6451332"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451332"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390261"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390261" local_id="4390261" ref="https://freezepeach.xyz/conversation/4183220">https://freezepeach.xyz/conversation/4183220</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://shitposter.club/api/statuses/show/7387553.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387553.atom"/> - <statusnet:notice_info local_id="7387553" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387539:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://mstdn.io/users/mayuutann&quot; class=&quot;h-card mention&quot; title=&quot;Mayutan&amp;#x2615;&quot;&gt;mayuutann&lt;/a&gt; ndndnd~</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387539"/> - <status_net notice_id="7387539"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:11:04+00:00</published> - <updated>2018-02-23T13:11:04+00:00</updated> - <thr:in-reply-to ref="https://mstdn.io/users/mayuutann/statuses/99574837619821505" href="https://mstdn.io/@mayuutann/99574837619821505"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/@mayuutann/99574837619821505"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390030"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390030" local_id="4390030" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=d05e2b056274c5ab">tag:shitposter.club,2018-02-23:objectType=thread:nonce=d05e2b056274c5ab</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mstdn.io/users/mayuutann"/> - <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://shitposter.club/api/statuses/show/7387539.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387539.atom"/> - <statusnet:notice_info local_id="7387539" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387518:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://mstdn.io/users/mayuutann&quot; class=&quot;h-card mention&quot; title=&quot;Mayutan&amp;#x2615;&quot;&gt;mayuutann&lt;/a&gt; well done! mayumayu is so energetic</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387518"/> - <status_net notice_id="7387518"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:08:50+00:00</published> - <updated>2018-02-23T13:08:50+00:00</updated> - <thr:in-reply-to ref="https://mstdn.io/users/mayuutann/statuses/99574826506801503" href="https://mstdn.io/@mayuutann/99574826506801503"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/@mayuutann/99574826506801503"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390030"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390030" local_id="4390030" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=d05e2b056274c5ab">tag:shitposter.club,2018-02-23:objectType=thread:nonce=d05e2b056274c5ab</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://mstdn.io/users/mayuutann"/> - <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://shitposter.club/api/statuses/show/7387518.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387518.atom"/> - <statusnet:notice_info local_id="7387518" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <id>tag:shitposter.club,2018-02-23:fave:5381:note:7387503:2018-02-23T13:08:00+00:00</id> - <title>Favorite</title> - <content type="html">shpuld favorited something by mayuutann: &lt;p&gt;done with FIGURE MAT!!&lt;br /&gt; (Posted with IFTTT)&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387511"/> - <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> - <published>2018-02-23T13:08:00+00:00</published> - <updated>2018-02-23T13:08:00+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>https://mstdn.io/users/mayuutann/statuses/99574825526201897</id> - <title>New note by mayuutann</title> - <content type="html">&lt;p&gt;done with FIGURE MAT!!&lt;br /&gt; (Posted with IFTTT)&lt;/p&gt;</content> - <link rel="alternate" type="text/html" href="https://mstdn.io/@mayuutann/99574825526201897"/> - <status_net notice_id="7387503"></status_net> - </activity:object> - <thr:in-reply-to ref="https://mstdn.io/users/mayuutann/statuses/99574825526201897" href="https://mstdn.io/@mayuutann/99574825526201897"></thr:in-reply-to> - <link rel="related" href="https://mstdn.io/@mayuutann/99574825526201897"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390240"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390240" local_id="4390240" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=c6aaa9b91e8d242f">tag:shitposter.club,2018-02-23:objectType=thread:nonce=c6aaa9b91e8d242f</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://shitposter.club/api/statuses/show/7387511.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387511.atom"/> - <statusnet:notice_info local_id="7387511" source="unknown"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387486:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; @&lt;a href=&quot;https://a.weirder.earth/users/mutstd&quot; class=&quot;h-card mention&quot; title=&quot;Mutant Standard&quot;&gt;mutstd&lt;/a&gt; @&lt;a href=&quot;https://donphan.social/users/Siphonay&quot; class=&quot;h-card mention&quot; title=&quot;Siphonay&quot;&gt;siphonay&lt;/a&gt; jokes on you I'm oppressively shitposting myself</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387486"/> - <status_net notice_id="7387486"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:05:44+00:00</published> - <updated>2018-02-23T13:05:44+00:00</updated> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451272:objectType=comment" href="https://freezepeach.xyz/notice/6451272"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451272"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4389665"/> - <ostatus:conversation href="https://shitposter.club/conversation/4389665" local_id="4389665" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=5d306467336c9661">tag:shitposter.club,2018-02-23:objectType=thread:nonce=5d306467336c9661</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://a.weirder.earth/users/mutstd"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://donphan.social/users/Siphonay"/> - <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://shitposter.club/api/statuses/show/7387486.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387486.atom"/> - <statusnet:notice_info local_id="7387486" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387466:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; @&lt;a href=&quot;https://a.weirder.earth/users/mutstd&quot; class=&quot;h-card mention&quot; title=&quot;Mutant Standard&quot;&gt;mutstd&lt;/a&gt; @&lt;a href=&quot;https://donphan.social/users/Siphonay&quot; class=&quot;h-card mention&quot; title=&quot;Siphonay&quot;&gt;siphonay&lt;/a&gt; how does it feel being hostile</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387466"/> - <status_net notice_id="7387466"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:04:10+00:00</published> - <updated>2018-02-23T13:04:10+00:00</updated> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451260:objectType=comment" href="https://freezepeach.xyz/notice/6451260"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451260"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4389665"/> - <ostatus:conversation href="https://shitposter.club/conversation/4389665" local_id="4389665" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=5d306467336c9661">tag:shitposter.club,2018-02-23:objectType=thread:nonce=5d306467336c9661</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://a.weirder.earth/users/mutstd"/> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://donphan.social/users/Siphonay"/> - <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://shitposter.club/api/statuses/show/7387466.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387466.atom"/> - <statusnet:notice_info local_id="7387466" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387459:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; gorogoro</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387459"/> - <status_net notice_id="7387459"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:03:32+00:00</published> - <updated>2018-02-23T13:03:32+00:00</updated> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451248:objectType=comment" href="https://freezepeach.xyz/notice/6451248"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451248"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4389271"/> - <ostatus:conversation href="https://shitposter.club/conversation/4389271" local_id="4389271" ref="https://freezepeach.xyz/conversation/4181784">https://freezepeach.xyz/conversation/4181784</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <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://shitposter.club/api/statuses/show/7387459.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387459.atom"/> - <statusnet:notice_info local_id="7387459" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387432:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://freezepeach.xyz/user/3458&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x5FA1;&amp;#x5712;&amp;#x306F;&amp;#x304F;&amp;#x3044;&quot;&gt;hakui&lt;/a&gt; ndnd</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387432"/> - <status_net notice_id="7387432"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T13:02:05+00:00</published> - <updated>2018-02-23T13:02:05+00:00</updated> - <thr:in-reply-to ref="tag:freezepeach.xyz,2018-02-23:noticeId=6451204:objectType=comment" href="https://freezepeach.xyz/notice/6451204"></thr:in-reply-to> - <link rel="related" href="https://freezepeach.xyz/notice/6451204"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4389271"/> - <ostatus:conversation href="https://shitposter.club/conversation/4389271" local_id="4389271" ref="https://freezepeach.xyz/conversation/4181784">https://freezepeach.xyz/conversation/4181784</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://freezepeach.xyz/user/3458"/> - <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://shitposter.club/api/statuses/show/7387432.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387432.atom"/> - <statusnet:notice_info local_id="7387432" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387367:objectType=note</id> - <title>New note by shpuld</title> - <content type="html">dear diary: I'm trying to do work but I can only think of tenshi eating a corndog</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387367"/> - <status_net notice_id="7387367"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T12:56:03+00:00</published> - <updated>2018-02-23T12:56:03+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390142"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390142" local_id="4390142" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=57f316da416743fc">tag:shitposter.club,2018-02-23:objectType=thread:nonce=57f316da416743fc</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://shitposter.club/api/statuses/show/7387367.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387367.atom"/> - <statusnet:notice_info local_id="7387367" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387354:objectType=note</id> - <title>New note by shpuld</title> - <content type="html">jesus christ it's such a fridey at work</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387354"/> - <status_net notice_id="7387354"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T12:53:50+00:00</published> - <updated>2018-02-23T12:53:50+00:00</updated> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390131"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390131" local_id="4390131" ref="tag:shitposter.club,2018-02-23:objectType=thread:nonce=c05eb5e91bdcbdb7">tag:shitposter.club,2018-02-23:objectType=thread:nonce=c05eb5e91bdcbdb7</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://shitposter.club/api/statuses/show/7387354.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387354.atom"/> - <statusnet:notice_info local_id="7387354" source="Pleroma FE"></statusnet:notice_info> -</entry> -<entry> - <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type> - <id>tag:shitposter.club,2018-02-23:noticeId=7387343:objectType=comment</id> - <title>New comment by shpuld</title> - <content type="html">@&lt;a href=&quot;https://gs.smuglo.li/user/589&quot; class=&quot;h-card mention&quot; title=&quot;&amp;#x16DE;&amp;#x16A9;&amp;#x16B3;&amp;#x16C1;&amp;#x16DE;&amp;#x16A9;&amp;#x16B3;&amp;#x16C1;&quot;&gt;dokidoki&lt;/a&gt; give them free upgrades to krokodil</content> - <link rel="alternate" type="text/html" href="https://shitposter.club/notice/7387343"/> - <status_net notice_id="7387343"></status_net> - <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> - <published>2018-02-23T12:53:15+00:00</published> - <updated>2018-02-23T12:53:15+00:00</updated> - <thr:in-reply-to ref="tag:gs.smuglo.li,2018-02-23:noticeId=6201061:objectType=note" href="https://gs.smuglo.li/notice/6201061"></thr:in-reply-to> - <link rel="related" href="https://gs.smuglo.li/notice/6201061"/> - <link rel="ostatus:conversation" href="https://shitposter.club/conversation/4390117"/> - <ostatus:conversation href="https://shitposter.club/conversation/4390117" local_id="4390117" ref="https://gs.smuglo.li/conversation/3934774">https://gs.smuglo.li/conversation/3934774</ostatus:conversation> - <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://gs.smuglo.li/user/589"/> - <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://shitposter.club/api/statuses/show/7387343.atom"/> - <link rel="edit" type="application/atom+xml" href="https://shitposter.club/api/statuses/show/7387343.atom"/> - <statusnet:notice_info local_id="7387343" source="Pleroma FE"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/fixtures/tesla_mock/wedistribute-create-article.json b/test/fixtures/tesla_mock/wedistribute-create-article.json @@ -0,0 +1 @@ +{"@context":["https:\/\/www.w3.org\/ns\/activitystreams"],"type":"Create","actor":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/actor\/-blog","object":{"@context":["https:\/\/www.w3.org\/ns\/activitystreams"],"type":"Article","name":"The end is near: Mastodon plans to drop OStatus support","content":"<!-- wp:paragraph {\"dropCap\":true} -->\n<p class=\"has-drop-cap\">The days of OStatus are numbered. The venerable protocol has served as a glue between many different types of servers since the early days of the Fediverse, connecting StatusNet (now GNU Social) to Friendica, Hubzilla, Mastodon, and Pleroma.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>Now that many fediverse platforms support ActivityPub as a successor protocol, Mastodon appears to be drawing a line in the sand. In <a href=\"https:\/\/www.patreon.com\/posts\/mastodon-2-9-and-28121681\">a Patreon update<\/a>, Eugen Rochko writes:<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:quote -->\n<blockquote class=\"wp-block-quote\"><p>...OStatus...has overstayed its welcome in the code...and now that most of the network uses ActivityPub, it's time for it to go. <\/p><cite>Eugen Rochko, Mastodon creator<\/cite><\/blockquote>\n<!-- \/wp:quote -->\n\n<!-- wp:paragraph -->\n<p>The <a href=\"https:\/\/github.com\/tootsuite\/mastodon\/pull\/11205\">pull request<\/a> to remove Pubsubhubbub and Salmon, two of the main components of OStatus, has already been merged into Mastodon's master branch.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>Some projects will be left in the dark as a side effect of this. GNU Social and PostActiv, for example, both only communicate using OStatus. While <a href=\"https:\/\/mastodon.social\/@dansup\/102076573310057902\">some discussion<\/a> exists regarding adopting ActivityPub for GNU Social, and <a href=\"https:\/\/notabug.org\/diogo\/gnu-social\/src\/activitypub\/plugins\/ActivityPub\">a plugin is in development<\/a>, it hasn't been formally adopted yet. We just hope that the <a href=\"https:\/\/status.fsf.org\/main\/public\">Free Software Foundation's instance<\/a> gets updated in time!<\/p>\n<!-- \/wp:paragraph -->","summary":"One of the largest platforms in the federated social web is dropping the protocol that it started with.","attributedTo":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/actor\/-blog","url":"https:\/\/wedistribute.org\/2019\/07\/mastodon-drops-ostatus\/","to":["https:\/\/www.w3.org\/ns\/activitystreams#Public","https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/actor\/-blog\/followers"],"id":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/object\/85810","likes":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/object\/85810\/likes","shares":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/object\/85810\/shares"},"to":["https:\/\/www.w3.org\/ns\/activitystreams#Public","https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/actor\/-blog\/followers"],"id":"https:\/\/wedistribute.org\/wp-json\/pterotype\/v1\/object\/85809"} +\ No newline at end of file diff --git a/test/fixtures/unfollow.xml b/test/fixtures/unfollow.xml @@ -1,68 +0,0 @@ -<?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-07T09:54:49+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>undo:tag:social.heldscal.la,2017-05-07:subscription:23211:person:44803:2017-05-07T09:54:48+00:00</id> - <title>Constance Variable (lambadalambda@social.heldscal.la)'s status on Sunday, 07-May-2017 09:54:49 UTC</title> - <content type="html">&lt;a href=&quot;https://social.heldscal.la/lambadalambda&quot;&gt;Constance Variable&lt;/a&gt; stopped following &lt;a href=&quot;https://pawoo.net/@pekorino&quot;&gt;mono&lt;/a&gt;.</content> - <link rel="alternate" type="text/html" href="https://social.heldscal.la/notice/2092981"/> - <activity:verb>http://activitystrea.ms/schema/1.0/unfollow</activity:verb> - <published>2017-05-07T09:54:49+00:00</published> - <updated>2017-05-07T09:54:49+00:00</updated> - <activity:object> - <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> - <id>https://pawoo.net/users/pekorino</id> - <title>mono</title> - <summary>http://shitposter.club/mono 孤独のグルメ</summary> - <link rel="alternate" type="text/html" href="https://pawoo.net/@pekorino"/> - <link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://social.heldscal.la/theme/neo-gnu/default-avatar-profile.png"/> - <link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://social.heldscal.la/theme/neo-gnu/default-avatar-stream.png"/> - <link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://social.heldscal.la/theme/neo-gnu/default-avatar-mini.png"/> - <poco:preferredUsername>pekorino</poco:preferredUsername> - <poco:displayName>mono</poco:displayName> - <poco:note>http://shitposter.club/mono 孤独のグルメ</poco:note> - </activity:object> - <link rel="ostatus:conversation" href="https://social.heldscal.la/conversation/1079786"/> - <ostatus:conversation href="https://social.heldscal.la/conversation/1079786" local_id="1079786" ref="tag:social.heldscal.la,2017-05-07:objectType=thread:nonce=6e80caf94e03029f">tag:social.heldscal.la,2017-05-07:objectType=thread:nonce=6e80caf94e03029f</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/2092981.atom"/> - <link rel="edit" type="application/atom+xml" href="https://social.heldscal.la/api/statuses/show/2092981.atom"/> - <statusnet:notice_info local_id="2092981" source="activity"></statusnet:notice_info> -</entry> -</feed> diff --git a/test/integration/mastodon_websocket_test.exs b/test/integration/mastodon_websocket_test.exs @@ -78,7 +78,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do Pleroma.Repo.insert( OAuth.App.register_changeset(%OAuth.App{}, %{ client_name: "client", - scopes: ["scope"], + scopes: ["read"], redirect_uris: "url" }) ) diff --git a/test/marker_test.exs b/test/marker_test.exs @@ -33,8 +33,8 @@ defmodule Pleroma.MarkerTest do test "returns user markers" do user = insert(:user) marker = insert(:marker, user: user) - insert(:notification, user: user) - insert(:notification, user: user) + insert(:notification, user: user, activity: insert(:note_activity)) + insert(:notification, user: user, activity: insert(:note_activity)) insert(:marker, timeline: "home", user: user) assert Marker.get_markers( diff --git a/test/notification_test.exs b/test/notification_test.exs @@ -179,17 +179,19 @@ defmodule Pleroma.NotificationTest do describe "create_notification" do @tag needs_streamer: true test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do - user = insert(:user) + %{user: user, token: oauth_token} = oauth_access(["read"]) task = Task.async(fn -> - Streamer.get_topic_and_add_socket("user", user) + {:ok, _topic} = Streamer.get_topic_and_add_socket("user", user, oauth_token) assert_receive {:render_with_user, _, _, _}, 4_000 end) task_user_notification = Task.async(fn -> - Streamer.get_topic_and_add_socket("user:notification", user) + {:ok, _topic} = + Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) + assert_receive {:render_with_user, _, _, _}, 4_000 end) diff --git a/test/object/fetcher_test.exs b/test/object/fetcher_test.exs @@ -6,10 +6,12 @@ defmodule Pleroma.Object.FetcherTest do use Pleroma.DataCase alias Pleroma.Activity + alias Pleroma.Config alias Pleroma.Object alias Pleroma.Object.Fetcher - import Tesla.Mock + import Mock + import Tesla.Mock setup do mock(fn @@ -71,20 +73,20 @@ defmodule Pleroma.Object.FetcherTest do setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) test "it returns thread depth exceeded error if thread depth is exceeded" do - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + Config.put([:instance, :federation_incoming_replies_max_depth], 0) assert {:error, "Max thread distance exceeded."} = Fetcher.fetch_object_from_id(@ap_id, depth: 1) end test "it fetches object if max thread depth is restricted to 0 and depth is not specified" do - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) + Config.put([:instance, :federation_incoming_replies_max_depth], 0) assert {:ok, _} = Fetcher.fetch_object_from_id(@ap_id) end test "it fetches object if requested depth does not exceed max thread depth" do - Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10) + Config.put([:instance, :federation_incoming_replies_max_depth], 10) assert {:ok, _} = Fetcher.fetch_object_from_id(@ap_id, depth: 10) end @@ -120,6 +122,16 @@ defmodule Pleroma.Object.FetcherTest do assert object == object_again end + + test "Return MRF reason when fetched status is rejected by one" do + clear_config([:mrf_keyword, :reject], ["yeah"]) + clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) + + assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} == + Fetcher.fetch_object_from_id( + "http://mastodon.example.org/@admin/99541947525187367" + ) + end end describe "implementation quirks" do @@ -212,7 +224,7 @@ defmodule Pleroma.Object.FetcherTest do Pleroma.Signature, [:passthrough], [] do - Pleroma.Config.put([:activitypub, :sign_object_fetches], true) + Config.put([:activitypub, :sign_object_fetches], true) Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367") @@ -223,7 +235,7 @@ defmodule Pleroma.Object.FetcherTest do Pleroma.Signature, [:passthrough], [] do - Pleroma.Config.put([:activitypub, :sign_object_fetches], false) + Config.put([:activitypub, :sign_object_fetches], false) Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367") diff --git a/test/plugs/oauth_plug_test.exs b/test/plugs/oauth_plug_test.exs @@ -16,7 +16,7 @@ defmodule Pleroma.Plugs.OAuthPlugTest do setup %{conn: conn} do user = insert(:user) - {:ok, %{token: token}} = Pleroma.Web.OAuth.Token.create_token(insert(:oauth_app), user) + {:ok, %{token: token}} = Pleroma.Web.OAuth.Token.create(insert(:oauth_app), user) %{user: user, token: token, conn: conn} end diff --git a/test/repo_test.exs b/test/repo_test.exs @@ -37,7 +37,9 @@ defmodule Pleroma.RepoTest do test "get one-to-many assoc from repo" do user = insert(:user) - notification = refresh_record(insert(:notification, user: user)) + + notification = + refresh_record(insert(:notification, user: user, activity: insert(:note_activity))) assert Repo.get_assoc(user, :notifications) == {:ok, [notification]} end @@ -47,4 +49,32 @@ defmodule Pleroma.RepoTest do assert Repo.get_assoc(token, :user) == {:error, :not_found} end end + + describe "chunk_stream/3" do + test "fetch records one-by-one" do + users = insert_list(50, :user) + + {fetch_users, 50} = + from(t in User) + |> Repo.chunk_stream(5) + |> Enum.reduce({[], 0}, fn %User{} = user, {acc, count} -> + {acc ++ [user], count + 1} + end) + + assert users == fetch_users + end + + test "fetch records in bulk" do + users = insert_list(50, :user) + + {fetch_users, 10} = + from(t in User) + |> Repo.chunk_stream(5, :batches) + |> Enum.reduce({[], 0}, fn users, {acc, count} -> + {acc ++ users, count + 1} + end) + + assert users == fetch_users + end + end end diff --git a/test/stats_test.exs b/test/stats_test.exs @@ -4,7 +4,10 @@ defmodule Pleroma.StatsTest do use Pleroma.DataCase + import Pleroma.Factory + + alias Pleroma.Stats alias Pleroma.Web.CommonAPI describe "user count" do @@ -13,7 +16,7 @@ defmodule Pleroma.StatsTest do _internal = insert(:user, local: true, nickname: nil) _internal = Pleroma.Web.ActivityPub.Relay.get_actor() - assert match?(%{stats: %{user_count: 1}}, Pleroma.Stats.calculate_stat_data()) + assert match?(%{stats: %{user_count: 1}}, Stats.calculate_stat_data()) end end @@ -47,23 +50,23 @@ defmodule Pleroma.StatsTest do end) assert %{"direct" => 3, "private" => 4, "public" => 1, "unlisted" => 2} = - Pleroma.Stats.get_status_visibility_count() + Stats.get_status_visibility_count() end test "on status delete" do user = insert(:user) {:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"}) - assert %{"public" => 1} = Pleroma.Stats.get_status_visibility_count() + assert %{"public" => 1} = Stats.get_status_visibility_count() CommonAPI.delete(activity.id, user) - assert %{"public" => 0} = Pleroma.Stats.get_status_visibility_count() + assert %{"public" => 0} = Stats.get_status_visibility_count() end test "on status visibility update" do user = insert(:user) {:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"}) - assert %{"public" => 1, "private" => 0} = Pleroma.Stats.get_status_visibility_count() + assert %{"public" => 1, "private" => 0} = Stats.get_status_visibility_count() {:ok, _} = CommonAPI.update_activity_scope(activity.id, %{visibility: "private"}) - assert %{"public" => 0, "private" => 1} = Pleroma.Stats.get_status_visibility_count() + assert %{"public" => 0, "private" => 1} = Stats.get_status_visibility_count() end test "doesn't count unrelated activities" do @@ -75,7 +78,7 @@ defmodule Pleroma.StatsTest do CommonAPI.repeat(activity.id, other_user) assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 0} = - Pleroma.Stats.get_status_visibility_count() + Stats.get_status_visibility_count() end end @@ -110,10 +113,10 @@ defmodule Pleroma.StatsTest do end) assert %{"direct" => 10, "private" => 0, "public" => 1, "unlisted" => 5} = - Pleroma.Stats.get_status_visibility_count(local_instance) + Stats.get_status_visibility_count(local_instance) assert %{"direct" => 0, "private" => 20, "public" => 0, "unlisted" => 0} = - Pleroma.Stats.get_status_visibility_count(instance2) + Stats.get_status_visibility_count(instance2) end end end diff --git a/test/support/data_case.ex b/test/support/data_case.ex @@ -27,6 +27,21 @@ defmodule Pleroma.DataCase do import Ecto.Query import Pleroma.DataCase use Pleroma.Tests.Helpers + + # Sets up OAuth access with specified scopes + defp oauth_access(scopes, opts \\ []) do + user = + Keyword.get_lazy(opts, :user, fn -> + Pleroma.Factory.insert(:user) + end) + + token = + Keyword.get_lazy(opts, :oauth_token, fn -> + Pleroma.Factory.insert(:oauth_token, user: user, scopes: scopes) + end) + + %{user: user, token: token} + end end end diff --git a/test/support/factory.ex b/test/support/factory.ex @@ -31,6 +31,7 @@ defmodule Pleroma.Factory do nickname: sequence(:nickname, &"nick#{&1}"), password_hash: Pbkdf2.hash_pwd_salt("test"), bio: sequence(:bio, &"Tester Number #{&1}"), + discoverable: true, last_digest_emailed_at: NaiveDateTime.utc_now(), last_refreshed_at: NaiveDateTime.utc_now(), notification_settings: %Pleroma.User.NotificationSetting{}, @@ -200,25 +201,6 @@ defmodule Pleroma.Factory do |> Map.merge(attrs) end - defp expiration_offset_by_minutes(attrs, minutes) do - scheduled_at = - NaiveDateTime.utc_now() - |> NaiveDateTime.add(:timer.minutes(minutes), :millisecond) - |> NaiveDateTime.truncate(:second) - - %Pleroma.ActivityExpiration{} - |> Map.merge(attrs) - |> Map.put(:scheduled_at, scheduled_at) - end - - def expiration_in_the_past_factory(attrs \\ %{}) do - expiration_offset_by_minutes(attrs, -60) - end - - def expiration_in_the_future_factory(attrs \\ %{}) do - expiration_offset_by_minutes(attrs, 61) - end - def article_activity_factory do article = insert(:article) diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex @@ -103,14 +103,6 @@ defmodule HttpRequestMock do }} end - def get("https://mastodon.social/users/emelie.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/emelie.atom") - }} - end - def get( "https://osada.macgirvin.com/.well-known/webfinger?resource=acct:mike@osada.macgirvin.com", _, @@ -137,14 +129,6 @@ defmodule HttpRequestMock do }} end - def get("https://pawoo.net/users/pekorino.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/https___pawoo.net_users_pekorino.atom") - }} - end - def get( "https://pawoo.net/.well-known/webfinger?resource=acct:https://pawoo.net/users/pekorino", _, @@ -159,19 +143,6 @@ defmodule HttpRequestMock do end def get( - "https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom", - _, - _, - _ - ) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/atarifrosch_feed.xml") - }} - end - - def get( "https://social.stopwatchingus-heidelberg.de/.well-known/webfinger?resource=acct:https://social.stopwatchingus-heidelberg.de/user/18330", _, _, @@ -184,27 +155,6 @@ defmodule HttpRequestMock do }} end - def get("https://mamot.fr/users/Skruyb.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/https___mamot.fr_users_Skruyb.atom") - }} - end - - def get( - "https://mamot.fr/.well-known/webfinger?resource=acct:https://mamot.fr/users/Skruyb", - _, - _, - [{"accept", "application/xrd+xml,application/jrd+json"}] - ) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/skruyb@mamot.fr.atom") - }} - end - def get( "https://social.heldscal.la/.well-known/webfinger?resource=nonexistant@social.heldscal.la", _, @@ -507,19 +457,6 @@ defmodule HttpRequestMock do }} end - def get( - "https://mamot.fr/.well-known/webfinger?resource=https://mamot.fr/users/Skruyb", - _, - _, - _ - ) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/skruyb@mamot.fr.atom") - }} - end - def get("http://pawoo.net/.well-known/host-meta", _, _, _) do {:ok, %Tesla.Env{ @@ -647,17 +584,6 @@ defmodule HttpRequestMock do }} end - def get("https://pleroma.soykaf.com/users/lain/feed.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: - File.read!( - "test/fixtures/tesla_mock/https___pleroma.soykaf.com_users_lain_feed.atom.xml" - ) - }} - end - def get(url, _, _, [{"accept", "application/xrd+xml,application/jrd+json"}]) when url in [ "https://pleroma.soykaf.com/.well-known/webfinger?resource=acct:https://pleroma.soykaf.com/users/lain", @@ -670,17 +596,6 @@ defmodule HttpRequestMock do }} end - def get("https://shitposter.club/api/statuses/user_timeline/1.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: - File.read!( - "test/fixtures/tesla_mock/https___shitposter.club_api_statuses_user_timeline_1.atom.xml" - ) - }} - end - def get( "https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/1", _, @@ -694,37 +609,10 @@ defmodule HttpRequestMock do }} end - def get("https://shitposter.club/notice/2827873", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/https___shitposter.club_notice_2827873.json") - }} - end - - def get("https://shitposter.club/api/statuses/show/2827873.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: - File.read!( - "test/fixtures/tesla_mock/https___shitposter.club_api_statuses_show_2827873.atom.xml" - ) - }} - end - def get("https://testing.pleroma.lol/objects/b319022a-4946-44c5-9de9-34801f95507b", _, _, _) do {:ok, %Tesla.Env{status: 200}} end - def get("https://shitposter.club/api/statuses/user_timeline/5381.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/spc_5381.atom") - }} - end - def get( "https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/5381", _, @@ -746,14 +634,6 @@ defmodule HttpRequestMock do }} end - def get("https://shitposter.club/api/statuses/show/7369654.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/7369654.atom") - }} - end - def get("https://shitposter.club/notice/4027863", _, _, _) do {:ok, %Tesla.Env{ @@ -762,14 +642,6 @@ defmodule HttpRequestMock do }} end - def get("https://social.sakamoto.gq/users/eal/feed.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/sakamoto_eal_feed.atom") - }} - end - def get("http://social.sakamoto.gq/.well-known/host-meta", _, _, _) do {:ok, %Tesla.Env{ @@ -791,15 +663,6 @@ defmodule HttpRequestMock do }} end - def get( - "https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056", - _, - _, - [{"accept", "application/atom+xml"}] - ) do - {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/sakamoto.atom")}} - end - def get("http://mastodon.social/.well-known/host-meta", _, _, _) do {:ok, %Tesla.Env{ @@ -853,28 +716,6 @@ defmodule HttpRequestMock do {:ok, %Tesla.Env{status: 406, body: ""}} end - def get("http://gs.example.org/index.php/api/statuses/user_timeline/1.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: - File.read!( - "test/fixtures/tesla_mock/http__gs.example.org_index.php_api_statuses_user_timeline_1.atom.xml" - ) - }} - end - - def get("https://social.heldscal.la/api/statuses/user_timeline/29191.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: - File.read!( - "test/fixtures/tesla_mock/https___social.heldscal.la_api_statuses_user_timeline_29191.atom.xml" - ) - }} - end - def get("http://squeet.me/.well-known/host-meta", _, _, _) do {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/squeet.me_host_meta")}} @@ -996,17 +837,6 @@ defmodule HttpRequestMock do }} end - def get("https://social.heldscal.la/api/statuses/user_timeline/23211.atom", _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: - File.read!( - "test/fixtures/tesla_mock/https___social.heldscal.la_api_statuses_user_timeline_23211.atom.xml" - ) - }} - end - def get( "https://social.heldscal.la/.well-known/webfinger?resource=https://social.heldscal.la/user/23211", _, @@ -1036,10 +866,6 @@ defmodule HttpRequestMock do }} end - def get("https://mastodon.social/users/lambadalambda.atom", _, _, _) do - {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/lambadalambda.atom")}} - end - def get("https://mastodon.social/users/lambadalambda", _, _, _) do {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/lambadalambda.json")}} end diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs @@ -40,6 +40,19 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do on_exit(fn -> Application.put_env(:quack, :level, initial) end) end + @tag capture_log: true + test "config migration refused when deprecated settings are found" do + clear_config([:media_proxy, :whitelist], ["domain_without_scheme.com"]) + assert Repo.all(ConfigDB) == [] + + Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs") + + assert_received {:mix_shell, :error, [message]} + + assert message =~ + "Migration is not allowed until all deprecation warnings have been resolved." + end + test "filtered settings are migrated to db" do assert Repo.all(ConfigDB) == [] diff --git a/test/tasks/database_test.exs b/test/tasks/database_test.exs @@ -3,14 +3,15 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Mix.Tasks.Pleroma.DatabaseTest do + use Pleroma.DataCase + use Oban.Testing, repo: Pleroma.Repo + alias Pleroma.Activity alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web.CommonAPI - use Pleroma.DataCase - import Pleroma.Factory setup_all do @@ -130,40 +131,45 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do describe "ensure_expiration" do test "it adds to expiration old statuses" do - %{id: activity_id1} = insert(:note_activity) + activity1 = insert(:note_activity) - %{id: activity_id2} = - insert(:note_activity, %{inserted_at: NaiveDateTime.from_iso8601!("2015-01-23 23:50:07")}) + {:ok, inserted_at, 0} = DateTime.from_iso8601("2015-01-23T23:50:07Z") + activity2 = insert(:note_activity, %{inserted_at: inserted_at}) - %{id: activity_id3} = activity3 = insert(:note_activity) + %{id: activity_id3} = insert(:note_activity) - expires_at = - NaiveDateTime.utc_now() - |> NaiveDateTime.add(60 * 61, :second) - |> NaiveDateTime.truncate(:second) + expires_at = DateTime.add(DateTime.utc_now(), 60 * 61) - Pleroma.ActivityExpiration.create(activity3, expires_at) + Pleroma.Workers.PurgeExpiredActivity.enqueue(%{ + activity_id: activity_id3, + expires_at: expires_at + }) Mix.Tasks.Pleroma.Database.run(["ensure_expiration"]) - expirations = - Pleroma.ActivityExpiration - |> order_by(:activity_id) - |> Repo.all() - - assert [ - %Pleroma.ActivityExpiration{ - activity_id: ^activity_id1 - }, - %Pleroma.ActivityExpiration{ - activity_id: ^activity_id2, - scheduled_at: ~N[2016-01-23 23:50:07] - }, - %Pleroma.ActivityExpiration{ - activity_id: ^activity_id3, - scheduled_at: ^expires_at - } - ] = expirations + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity1.id}, + scheduled_at: + activity1.inserted_at + |> DateTime.from_naive!("Etc/UTC") + |> Timex.shift(days: 365) + ) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity2.id}, + scheduled_at: + activity2.inserted_at + |> DateTime.from_naive!("Etc/UTC") + |> Timex.shift(days: 365) + ) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity_id3}, + scheduled_at: expires_at + ) end end end diff --git a/test/tasks/frontend_test.exs b/test/tasks/frontend_test.exs @@ -48,11 +48,18 @@ defmodule Pleroma.FrontendTest do } }) + folder = Path.join([@dir, "frontends", "pleroma", "fantasy"]) + previously_existing = Path.join([folder, "temp"]) + File.mkdir_p!(folder) + File.write!(previously_existing, "yey") + assert File.exists?(previously_existing) + capture_io(fn -> Frontend.run(["install", "pleroma", "--file", "test/fixtures/tesla_mock/frontend.zip"]) end) - assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"])) + assert File.exists?(Path.join([folder, "test.txt"])) + refute File.exists?(previously_existing) end test "it downloads and unzips unknown frontends" do diff --git a/test/user/import_test.exs b/test/user/import_test.exs @@ -0,0 +1,76 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.User.ImportTest do + alias Pleroma.Repo + alias Pleroma.Tests.ObanHelpers + alias Pleroma.User + + use Pleroma.DataCase + use Oban.Testing, repo: Pleroma.Repo + + import Pleroma.Factory + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + :ok + end + + describe "follow_import" do + test "it imports user followings from list" do + [user1, user2, user3] = insert_list(3, :user) + + identifiers = [ + user2.ap_id, + user3.nickname + ] + + {:ok, job} = User.Import.follow_import(user1, identifiers) + + assert {:ok, result} = ObanHelpers.perform(job) + assert is_list(result) + assert result == [user2, user3] + assert User.following?(user1, user2) + assert User.following?(user1, user3) + end + end + + describe "blocks_import" do + test "it imports user blocks from list" do + [user1, user2, user3] = insert_list(3, :user) + + identifiers = [ + user2.ap_id, + user3.nickname + ] + + {:ok, job} = User.Import.blocks_import(user1, identifiers) + + assert {:ok, result} = ObanHelpers.perform(job) + assert is_list(result) + assert result == [user2, user3] + assert User.blocks?(user1, user2) + assert User.blocks?(user1, user3) + end + end + + describe "mutes_import" do + test "it imports user mutes from list" do + [user1, user2, user3] = insert_list(3, :user) + + identifiers = [ + user2.ap_id, + user3.nickname + ] + + {:ok, job} = User.Import.mutes_import(user1, identifiers) + + assert {:ok, result} = ObanHelpers.perform(job) + assert is_list(result) + assert result == [user2, user3] + assert User.mutes?(user1, user2) + assert User.mutes?(user1, user3) + end + end +end diff --git a/test/user_search_test.exs b/test/user_search_test.exs @@ -25,6 +25,14 @@ defmodule Pleroma.UserSearchTest do assert found_user.id == user.id end + test "excludes users when discoverable is false" do + insert(:user, %{nickname: "john 3000", discoverable: false}) + insert(:user, %{nickname: "john 3001"}) + + users = User.search("john") + assert Enum.count(users) == 1 + end + test "excludes service actors from results" do insert(:user, actor_type: "Application", nickname: "user1") service = insert(:user, actor_type: "Service", nickname: "user2") diff --git a/test/user_test.exs b/test/user_test.exs @@ -976,23 +976,6 @@ defmodule Pleroma.UserTest do end end - describe "follow_import" do - test "it imports user followings from list" do - [user1, user2, user3] = insert_list(3, :user) - - identifiers = [ - user2.ap_id, - user3.nickname - ] - - {:ok, job} = User.follow_import(user1, identifiers) - - assert {:ok, result} = ObanHelpers.perform(job) - assert is_list(result) - assert result == [user2, user3] - end - end - describe "mutes" do test "it mutes people" do user = insert(:user) @@ -1199,23 +1182,6 @@ defmodule Pleroma.UserTest do end end - describe "blocks_import" do - test "it imports user blocks from list" do - [user1, user2, user3] = insert_list(3, :user) - - identifiers = [ - user2.ap_id, - user3.nickname - ] - - {:ok, job} = User.blocks_import(user1, identifiers) - - assert {:ok, result} = ObanHelpers.perform(job) - assert is_list(result) - assert result == [user2, user3] - end - end - describe "get_recipients_from_activity" do test "works for announces" do actor = insert(:user) @@ -1510,7 +1476,7 @@ defmodule Pleroma.UserTest do user = User.get_by_id(user.id) assert %User{ - bio: nil, + bio: "", raw_bio: nil, email: nil, name: nil, @@ -1681,7 +1647,7 @@ defmodule Pleroma.UserTest do assert User.visible_for(user, user) == :visible end - test "returns false when the account is unauthenticated and auth is required" do + test "returns false when the account is unconfirmed and confirmation is required" do Pleroma.Config.put([:instance, :account_activation_required], true) user = insert(:user, local: true, confirmation_pending: true) @@ -1690,14 +1656,23 @@ defmodule Pleroma.UserTest do refute User.visible_for(user, other_user) == :visible end - test "returns true when the account is unauthenticated and auth is not required" do + test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do + Pleroma.Config.put([:instance, :account_activation_required], true) + + user = insert(:user, local: false, confirmation_pending: true) + other_user = insert(:user, local: true) + + assert User.visible_for(user, other_user) == :visible + end + + test "returns true when the account is unconfirmed and confirmation is not required" do user = insert(:user, local: true, confirmation_pending: true) other_user = insert(:user, local: true) assert User.visible_for(user, other_user) == :visible end - test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do + test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do Pleroma.Config.put([:instance, :account_activation_required], true) user = insert(:user, local: true, confirmation_pending: true) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs @@ -239,7 +239,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do } } - assert {:error, {:remote_limit_error, _}} = ActivityPub.insert(data) + assert {:error, :remote_limit} = ActivityPub.insert(data) end test "doesn't drop activities with content being null" do @@ -386,9 +386,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end describe "create activities" do - test "it reverts create" do - user = insert(:user) + setup do + [user: insert(:user)] + end + test "it reverts create", %{user: user} do with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do assert {:error, :reverted} = ActivityPub.create(%{ @@ -407,9 +409,47 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert Repo.aggregate(Object, :count, :id) == 0 end - test "removes doubled 'to' recipients" do - user = insert(:user) + test "creates activity if expiration is not configured and expires_at is not passed", %{ + user: user + } do + clear_config([Pleroma.Workers.PurgeExpiredActivity, :enabled], false) + + assert {:ok, _} = + ActivityPub.create(%{ + to: ["user1", "user2"], + actor: user, + context: "", + object: %{ + "to" => ["user1", "user2"], + "type" => "Note", + "content" => "testing" + } + }) + end + + test "rejects activity if expires_at present but expiration is not configured", %{user: user} do + clear_config([Pleroma.Workers.PurgeExpiredActivity, :enabled], false) + + assert {:error, :expired_activities_disabled} = + ActivityPub.create(%{ + to: ["user1", "user2"], + actor: user, + context: "", + object: %{ + "to" => ["user1", "user2"], + "type" => "Note", + "content" => "testing" + }, + additional: %{ + "expires_at" => DateTime.utc_now() + } + }) + assert Repo.aggregate(Activity, :count, :id) == 0 + assert Repo.aggregate(Object, :count, :id) == 0 + end + + test "removes doubled 'to' recipients", %{user: user} do {:ok, activity} = ActivityPub.create(%{ to: ["user1", "user1", "user2"], @@ -427,9 +467,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert activity.recipients == ["user1", "user2", user.ap_id] end - test "increases user note count only for public activities" do - user = insert(:user) - + test "increases user note count only for public activities", %{user: user} do {:ok, _} = CommonAPI.post(User.get_cached_by_id(user.id), %{ status: "1", @@ -458,8 +496,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert user.note_count == 2 end - test "increases replies count" do - user = insert(:user) + test "increases replies count", %{user: user} do user2 = insert(:user) {:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"}) @@ -2077,18 +2114,25 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end describe "global activity expiration" do - setup do: clear_config([:mrf, :policies]) - test "creates an activity expiration for local Create activities" do - Pleroma.Config.put( - [:mrf, :policies], - Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy + clear_config([:mrf, :policies], Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy) + + {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"}) + {:ok, follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"}) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity.id}, + scheduled_at: + activity.inserted_at + |> DateTime.from_naive!("Etc/UTC") + |> Timex.shift(days: 365) ) - {:ok, %{id: id_create}} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"}) - {:ok, _follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"}) - - assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all() + refute_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: follow.id} + ) end end diff --git a/test/web/activity_pub/mrf/activity_expiration_policy_test.exs b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs @@ -18,11 +18,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do "object" => %{"type" => "Note"} }) - assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364 + assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364 end test "keeps existing `expires_at` if it less than the config setting" do - expires_at = NaiveDateTime.utc_now() |> Timex.shift(days: 1) + expires_at = DateTime.utc_now() |> Timex.shift(days: 1) assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} = ActivityExpirationPolicy.filter(%{ @@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do end test "overwrites existing `expires_at` if it greater than the config setting" do - too_distant_future = NaiveDateTime.utc_now() |> Timex.shift(years: 2) + too_distant_future = DateTime.utc_now() |> Timex.shift(years: 2) assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} = ActivityExpirationPolicy.filter(%{ @@ -46,7 +46,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do "object" => %{"type" => "Note"} }) - assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364 + assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364 end test "ignores remote activities" do diff --git a/test/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs b/test/web/activity_pub/mrf/force_bot_unlisted_policy_test.exs @@ -0,0 +1,60 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicyTest do + use Pleroma.DataCase + import Pleroma.Factory + + alias Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy + @public "https://www.w3.org/ns/activitystreams#Public" + + defp generate_messages(actor) do + {%{ + "actor" => actor.ap_id, + "type" => "Create", + "object" => %{}, + "to" => [@public, "f"], + "cc" => [actor.follower_address, "d"] + }, + %{ + "actor" => actor.ap_id, + "type" => "Create", + "object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]}, + "to" => ["f", actor.follower_address], + "cc" => ["d", @public] + }} + end + + test "removes from the federated timeline by nickname heuristics 1" do + actor = insert(:user, %{nickname: "annoying_ebooks@example.com"}) + + {message, except_message} = generate_messages(actor) + + assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message} + end + + test "removes from the federated timeline by nickname heuristics 2" do + actor = insert(:user, %{nickname: "cirnonewsnetworkbot@meow.cat"}) + + {message, except_message} = generate_messages(actor) + + assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message} + end + + test "removes from the federated timeline by actor type Application" do + actor = insert(:user, %{actor_type: "Application"}) + + {message, except_message} = generate_messages(actor) + + assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message} + end + + test "removes from the federated timeline by actor type Service" do + actor = insert(:user, %{actor_type: "Service"}) + + {message, except_message} = generate_messages(actor) + + assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message} + end +end diff --git a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs b/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs @@ -22,6 +22,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do } } + setup do: clear_config([:media_proxy, :enabled], true) + test "it prefetches media proxy URIs" do with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do MediaProxyWarmingPolicy.filter(@message) diff --git a/test/web/activity_pub/object_validators/article_note_validator_test.exs b/test/web/activity_pub/object_validators/article_note_validator_test.exs @@ -0,0 +1,35 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidatorTest do + use Pleroma.DataCase + + alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator + alias Pleroma.Web.ActivityPub.Utils + + import Pleroma.Factory + + describe "Notes" do + setup do + user = insert(:user) + + note = %{ + "id" => Utils.generate_activity_id(), + "type" => "Note", + "actor" => user.ap_id, + "to" => [user.follower_address], + "cc" => [], + "content" => "Hellow this is content.", + "context" => "xxx", + "summary" => "a post" + } + + %{user: user, note: note} + end + + test "a basic note validates", %{note: note} do + %{valid?: true} = ArticleNoteValidator.cast_and_validate(note) + end + end +end diff --git a/test/web/activity_pub/object_validators/chat_validation_test.exs b/test/web/activity_pub/object_validators/chat_validation_test.exs @@ -69,6 +69,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) assert Map.put(valid_chat_message, "attachment", nil) == object + assert match?(%{"firefox" => _}, object["emoji"]) end test "validates for a basic object with an attachment", %{ diff --git a/test/web/activity_pub/object_validators/note_validator_test.exs b/test/web/activity_pub/object_validators/note_validator_test.exs @@ -1,35 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidatorTest do - use Pleroma.DataCase - - alias Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator - alias Pleroma.Web.ActivityPub.Utils - - import Pleroma.Factory - - describe "Notes" do - setup do - user = insert(:user) - - note = %{ - "id" => Utils.generate_activity_id(), - "type" => "Note", - "actor" => user.ap_id, - "to" => [user.follower_address], - "cc" => [], - "content" => "Hellow this is content.", - "context" => "xxx", - "summary" => "a post" - } - - %{user: user, note: note} - end - - test "a basic note validates", %{note: note} do - %{valid?: true} = NoteValidator.cast_and_validate(note) - end - end -end diff --git a/test/web/activity_pub/transmogrifier/article_handling_test.exs b/test/web/activity_pub/transmogrifier/article_handling_test.exs @@ -0,0 +1,75 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.ArticleHandlingTest do + use Oban.Testing, repo: Pleroma.Repo + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.Object.Fetcher + alias Pleroma.Web.ActivityPub.Transmogrifier + + test "Pterotype (Wordpress Plugin) Article" do + Tesla.Mock.mock(fn %{url: "https://wedistribute.org/wp-json/pterotype/v1/actor/-blog"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/wedistribute-user.json")} + end) + + data = + File.read!("test/fixtures/tesla_mock/wedistribute-create-article.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + object = Object.normalize(data["object"]) + + assert object.data["name"] == "The end is near: Mastodon plans to drop OStatus support" + + assert object.data["summary"] == + "One of the largest platforms in the federated social web is dropping the protocol that it started with." + + assert object.data["url"] == "https://wedistribute.org/2019/07/mastodon-drops-ostatus/" + end + + test "Plume Article" do + Tesla.Mock.mock(fn + %{url: "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"} -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/baptiste.gelex.xyz-article.json") + } + + %{url: "https://baptiste.gelez.xyz/@/BaptisteGelez"} -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/baptiste.gelex.xyz-user.json") + } + end) + + {:ok, object} = + Fetcher.fetch_object_from_id( + "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" + ) + + assert object.data["name"] == "This Month in Plume: June 2018" + + assert object.data["url"] == + "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" + end + + test "Prismo Article" do + Tesla.Mock.mock(fn %{url: "https://prismo.news/@mxb"} -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/https___prismo.news__mxb.json") + } + end) + + data = File.read!("test/fixtures/prismo-url-map.json") |> Jason.decode!() + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + object = Object.normalize(data["object"]) + + assert object.data["url"] == "https://prismo.news/posts/83" + end +end diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs @@ -106,6 +106,57 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do assert Enum.sort(object.data["oneOf"]) == Enum.sort(options) end + test "Mastodon Question activity with custom emojis" do + options = [ + %{ + "type" => "Note", + "name" => ":blobcat:", + "replies" => %{"totalItems" => 0, "type" => "Collection"} + }, + %{ + "type" => "Note", + "name" => ":blobfox:", + "replies" => %{"totalItems" => 0, "type" => "Collection"} + } + ] + + tag = [ + %{ + "icon" => %{ + "type" => "Image", + "url" => "https://blob.cat/emoji/custom/blobcats/blobcat.png" + }, + "id" => "https://blob.cat/emoji/custom/blobcats/blobcat.png", + "name" => ":blobcat:", + "type" => "Emoji", + "updated" => "1970-01-01T00:00:00Z" + }, + %{ + "icon" => %{"type" => "Image", "url" => "https://blob.cat/emoji/blobfox/blobfox.png"}, + "id" => "https://blob.cat/emoji/blobfox/blobfox.png", + "name" => ":blobfox:", + "type" => "Emoji", + "updated" => "1970-01-01T00:00:00Z" + } + ] + + data = + File.read!("test/fixtures/mastodon-question-activity.json") + |> Poison.decode!() + |> Kernel.put_in(["object", "oneOf"], options) + |> Kernel.put_in(["object", "tag"], tag) + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + object = Object.normalize(activity, false) + + assert object.data["oneOf"] == options + + assert object.data["emoji"] == %{ + "blobcat" => "https://blob.cat/emoji/custom/blobcats/blobcat.png", + "blobfox" => "https://blob.cat/emoji/blobfox/blobfox.png" + } + end + test "returns an error if received a second time" do data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() diff --git a/test/web/activity_pub/transmogrifier/video_handling_test.exs b/test/web/activity_pub/transmogrifier/video_handling_test.exs @@ -0,0 +1,93 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.VideoHandlingTest do + use Oban.Testing, repo: Pleroma.Repo + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.Object.Fetcher + alias Pleroma.Web.ActivityPub.Transmogrifier + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + :ok + end + + test "skip converting the content when it is nil" do + data = + File.read!("test/fixtures/tesla_mock/framatube.org-video.json") + |> Jason.decode!() + |> Kernel.put_in(["object", "content"], nil) + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + + assert object = Object.normalize(activity, false) + + assert object.data["content"] == nil + end + + test "it converts content of object to html" do + data = File.read!("test/fixtures/tesla_mock/framatube.org-video.json") |> Jason.decode!() + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + + assert object = Object.normalize(activity, false) + + assert object.data["content"] == + "<p>Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?</p><p>Transcription par @aprilorg ici : <a href=\"https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft\">https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft</a></p>" + end + + test "it remaps video URLs as attachments if necessary" do + {:ok, object} = + Fetcher.fetch_object_from_id( + "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" + ) + + assert object.data["url"] == + "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" + + assert object.data["attachment"] == [ + %{ + "type" => "Link", + "mediaType" => "video/mp4", + "name" => nil, + "url" => [ + %{ + "href" => + "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", + "mediaType" => "video/mp4", + "type" => "Link" + } + ] + } + ] + + data = File.read!("test/fixtures/tesla_mock/framatube.org-video.json") |> Jason.decode!() + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + + assert object = Object.normalize(activity, false) + + assert object.data["attachment"] == [ + %{ + "type" => "Link", + "mediaType" => "video/mp4", + "name" => nil, + "url" => [ + %{ + "href" => + "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", + "mediaType" => "video/mp4", + "type" => "Link" + } + ] + } + ] + + assert object.data["url"] == + "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" + end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do alias Pleroma.Activity alias Pleroma.Object - alias Pleroma.Object.Fetcher alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.Web.ActivityPub.Transmogrifier @@ -45,15 +44,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert "test" in object.data["tag"] end - test "it works for incoming notices with url not being a string (prismo)" do - data = File.read!("test/fixtures/prismo-url-map.json") |> Poison.decode!() - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - object = Object.normalize(data["object"]) - - assert object.data["url"] == "https://prismo.news/posts/83" - end - test "it cleans up incoming notices which are not really DMs" do user = insert(:user) other_user = insert(:user) @@ -105,7 +95,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do object = data["object"] - |> Map.put("inReplyTo", "https://shitposter.club/notice/2827873") + |> Map.put("inReplyTo", "https://mstdn.io/users/mayuutann/statuses/99568293732299394") data = Map.put(data, "object", object) {:ok, returned_activity} = Transmogrifier.handle_incoming(data) @@ -113,10 +103,11 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert activity = Activity.get_create_by_object_ap_id( - "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" ) - assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873" + assert returned_object.data["inReplyTo"] == + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" end test "it does not fetch reply-to activities beyond max replies depth limit" do @@ -140,8 +131,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" ) - assert returned_object.data["inReplyToAtomUri"] == - "https://shitposter.club/notice/2827873" + assert returned_object.data["inReplyTo"] == "https://shitposter.club/notice/2827873" end end @@ -355,83 +345,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do refute User.following?(User.get_cached_by_ap_id(data["actor"]), user) end - test "skip converting the content when it is nil" do - object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe" - - {:ok, object} = Fetcher.fetch_and_contain_remote_object_from_id(object_id) - - result = - Pleroma.Web.ActivityPub.Transmogrifier.fix_object(Map.merge(object, %{"content" => nil})) - - assert result["content"] == nil - end - - test "it converts content of object to html" do - object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe" - - {:ok, %{"content" => content_markdown}} = - Fetcher.fetch_and_contain_remote_object_from_id(object_id) - - {:ok, %Pleroma.Object{data: %{"content" => content}} = object} = - Fetcher.fetch_object_from_id(object_id) - - assert content_markdown == - "Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership\n\nTwenty Years in Jail: FreeBSD's Jails, Then and Now\n\nJails started as a limited virtualization system, but over the last two years they've..." - - assert content == - "<p>Support this and our other Michigan!/usr/group videos and meetings. Learn more at <a href=\"http://mug.org/membership\">http://mug.org/membership</a></p><p>Twenty Years in Jail: FreeBSD’s Jails, Then and Now</p><p>Jails started as a limited virtualization system, but over the last two years they’ve…</p>" - - assert object.data["mediaType"] == "text/html" - end - - test "it remaps video URLs as attachments if necessary" do - {:ok, object} = - Fetcher.fetch_object_from_id( - "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" - ) - - assert object.data["url"] == - "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" - - assert object.data["attachment"] == [ - %{ - "type" => "Link", - "mediaType" => "video/mp4", - "url" => [ - %{ - "href" => - "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", - "mediaType" => "video/mp4", - "type" => "Link" - } - ] - } - ] - - {:ok, object} = - Fetcher.fetch_object_from_id( - "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" - ) - - assert object.data["attachment"] == [ - %{ - "type" => "Link", - "mediaType" => "video/mp4", - "url" => [ - %{ - "href" => - "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", - "mediaType" => "video/mp4", - "type" => "Link" - } - ] - } - ] - - assert object.data["url"] == - "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" - end - test "it accepts Flag activities" do user = insert(:user) other_user = insert(:user) @@ -1072,7 +985,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert Transmogrifier.fix_in_reply_to(data) == data end - test "returns object with inReplyToAtomUri when denied incoming reply", %{data: data} do + test "returns object with inReplyTo when denied incoming reply", %{data: data} do Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) object_with_reply = @@ -1080,26 +993,22 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873" - assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873" object_with_reply = Map.put(data["object"], "inReplyTo", %{"id" => "https://shitposter.club/notice/2827873"}) modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) assert modified_object["inReplyTo"] == %{"id" => "https://shitposter.club/notice/2827873"} - assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873" object_with_reply = Map.put(data["object"], "inReplyTo", ["https://shitposter.club/notice/2827873"]) modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) assert modified_object["inReplyTo"] == ["https://shitposter.club/notice/2827873"] - assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873" object_with_reply = Map.put(data["object"], "inReplyTo", []) modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) assert modified_object["inReplyTo"] == [] - assert modified_object["inReplyToAtomUri"] == "" end @tag capture_log: true @@ -1108,19 +1017,17 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do Map.put( data["object"], "inReplyTo", - "https://shitposter.club/notice/2827873" + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" ) Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 5) modified_object = Transmogrifier.fix_in_reply_to(object_with_reply) assert modified_object["inReplyTo"] == - "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" - - assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873" + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" assert modified_object["context"] == - "tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26" + "tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4" end end @@ -1139,75 +1046,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do } end - test "fixes data for video object" do - object = %{ - "type" => "Video", - "url" => [ - %{ - "type" => "Link", - "mimeType" => "video/mp4", - "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4" - }, - %{ - "type" => "Link", - "mimeType" => "video/mp4", - "href" => "https://peertube46fb-ad81-2d4c2d1630e3-240.mp4" - }, - %{ - "type" => "Link", - "mimeType" => "text/html", - "href" => "https://peertube.-2d4c2d1630e3" - }, - %{ - "type" => "Link", - "mimeType" => "text/html", - "href" => "https://peertube.-2d4c2d16377-42" - } - ] - } - - assert Transmogrifier.fix_url(object) == %{ - "attachment" => [ - %{ - "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4", - "mimeType" => "video/mp4", - "type" => "Link" - } - ], - "type" => "Video", - "url" => "https://peertube.-2d4c2d1630e3" - } - end - - test "fixes url for not Video object" do - object = %{ - "type" => "Text", - "url" => [ - %{ - "type" => "Link", - "mimeType" => "text/html", - "href" => "https://peertube.-2d4c2d1630e3" - }, - %{ - "type" => "Link", - "mimeType" => "text/html", - "href" => "https://peertube.-2d4c2d16377-42" - } - ] - } - - assert Transmogrifier.fix_url(object) == %{ - "type" => "Text", - "url" => "https://peertube.-2d4c2d1630e3" - } - - assert Transmogrifier.fix_url(%{"type" => "Text", "url" => []}) == %{ - "type" => "Text", - "url" => "" - } - end - - test "retunrs not modified object" do + test "returns non-modified object" do assert Transmogrifier.fix_url(%{"type" => "Text"}) == %{"type" => "Text"} end end @@ -1222,7 +1061,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do @tag capture_log: true test "returns {:ok, %Object{}} for success case" do assert {:ok, %Object{}} = - Transmogrifier.get_obj_helper("https://shitposter.club/notice/2827873") + Transmogrifier.get_obj_helper( + "https://mstdn.io/users/mayuutann/statuses/99568293732299394" + ) end end diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -203,7 +203,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do assert user.note_count == 0 assert user.follower_count == 0 assert user.following_count == 0 - assert user.bio == nil + assert user.bio == "" assert user.name == nil assert called(Pleroma.Web.Federator.publish(:_)) @@ -1510,6 +1510,56 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end end + describe "GET /api/pleroma/admin/users/:nickname/chats" do + setup do + user = insert(:user) + recipients = insert_list(3, :user) + + Enum.each(recipients, fn recipient -> + CommonAPI.post_chat_message(user, recipient, "yo") + end) + + %{user: user} + end + + test "renders user's chats", %{conn: conn, user: user} do + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/chats") + + assert json_response(conn, 200) |> length() == 3 + end + end + + describe "GET /api/pleroma/admin/users/:nickname/chats unauthorized" do + setup do + user = insert(:user) + recipient = insert(:user) + CommonAPI.post_chat_message(user, recipient, "yo") + %{conn: conn} = oauth_access(["read:chats"]) + %{conn: conn, user: user} + end + + test "returns 403", %{conn: conn, user: user} do + conn + |> get("/api/pleroma/admin/users/#{user.nickname}/chats") + |> json_response(403) + end + end + + describe "GET /api/pleroma/admin/users/:nickname/chats unauthenticated" do + setup do + user = insert(:user) + recipient = insert(:user) + CommonAPI.post_chat_message(user, recipient, "yo") + %{conn: build_conn(), user: user} + end + + test "returns 403", %{conn: conn, user: user} do + conn + |> get("/api/pleroma/admin/users/#{user.nickname}/chats") + |> json_response(403) + end + end + describe "GET /api/pleroma/admin/moderation_log" do setup do moderator = insert(:user, is_moderator: true) diff --git a/test/web/admin_api/controllers/chat_controller_test.exs b/test/web/admin_api/controllers/chat_controller_test.exs @@ -0,0 +1,219 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.ChatControllerTest do + use Pleroma.Web.ConnCase + + import Pleroma.Factory + + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference + alias Pleroma.Config + alias Pleroma.ModerationLog + alias Pleroma.Object + alias Pleroma.Repo + alias Pleroma.Web.CommonAPI + + defp admin_setup do + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + + {:ok, %{admin: admin, token: token, conn: conn}} + end + + describe "DELETE /api/pleroma/admin/chats/:id/messages/:message_id" do + setup do: admin_setup() + + test "it deletes a message from the chat", %{conn: conn, admin: admin} do + user = insert(:user) + recipient = insert(:user) + + {:ok, message} = + CommonAPI.post_chat_message(user, recipient, "Hello darkness my old friend") + + object = Object.normalize(message, false) + + chat = Chat.get(user.id, recipient.ap_id) + recipient_chat = Chat.get(recipient.id, user.ap_id) + + cm_ref = MessageReference.for_chat_and_object(chat, object) + recipient_cm_ref = MessageReference.for_chat_and_object(recipient_chat, object) + + result = + conn + |> put_req_header("content-type", "application/json") + |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") + |> json_response_and_validate_schema(200) + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} deleted chat message ##{cm_ref.id}" + + assert result["id"] == cm_ref.id + refute MessageReference.get_by_id(cm_ref.id) + refute MessageReference.get_by_id(recipient_cm_ref.id) + assert %{data: %{"type" => "Tombstone"}} = Object.get_by_id(object.id) + end + end + + describe "GET /api/pleroma/admin/chats/:id/messages" do + setup do: admin_setup() + + test "it paginates", %{conn: conn} do + user = insert(:user) + recipient = insert(:user) + + Enum.each(1..30, fn _ -> + {:ok, _} = CommonAPI.post_chat_message(user, recipient, "hey") + end) + + chat = Chat.get(user.id, recipient.ap_id) + + result = + conn + |> get("/api/pleroma/admin/chats/#{chat.id}/messages") + |> json_response_and_validate_schema(200) + + assert length(result) == 20 + + result = + conn + |> get("/api/pleroma/admin/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}") + |> json_response_and_validate_schema(200) + + assert length(result) == 10 + end + + test "it returns the messages for a given chat", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + third_user = insert(:user) + + {:ok, _} = CommonAPI.post_chat_message(user, other_user, "hey") + {:ok, _} = CommonAPI.post_chat_message(user, third_user, "hey") + {:ok, _} = CommonAPI.post_chat_message(user, other_user, "how are you?") + {:ok, _} = CommonAPI.post_chat_message(other_user, user, "fine, how about you?") + + chat = Chat.get(user.id, other_user.ap_id) + + result = + conn + |> get("/api/pleroma/admin/chats/#{chat.id}/messages") + |> json_response_and_validate_schema(200) + + result + |> Enum.each(fn message -> + assert message["chat_id"] == chat.id |> to_string() + end) + + assert length(result) == 3 + end + end + + describe "GET /api/pleroma/admin/chats/:id" do + setup do: admin_setup() + + test "it returns a chat", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + + {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + + result = + conn + |> get("/api/pleroma/admin/chats/#{chat.id}") + |> json_response_and_validate_schema(200) + + assert result["id"] == to_string(chat.id) + assert %{} = result["sender"] + assert %{} = result["receiver"] + refute result["account"] + end + end + + describe "unauthorized chat moderation" do + setup do + user = insert(:user) + recipient = insert(:user) + + {:ok, message} = CommonAPI.post_chat_message(user, recipient, "Yo") + object = Object.normalize(message, false) + chat = Chat.get(user.id, recipient.ap_id) + cm_ref = MessageReference.for_chat_and_object(chat, object) + + %{conn: conn} = oauth_access(["read:chats", "write:chats"]) + %{conn: conn, chat: chat, cm_ref: cm_ref} + end + + test "DELETE /api/pleroma/admin/chats/:id/messages/:message_id", %{ + conn: conn, + chat: chat, + cm_ref: cm_ref + } do + conn + |> put_req_header("content-type", "application/json") + |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") + |> json_response(403) + + assert MessageReference.get_by_id(cm_ref.id) == cm_ref + end + + test "GET /api/pleroma/admin/chats/:id/messages", %{conn: conn, chat: chat} do + conn + |> get("/api/pleroma/admin/chats/#{chat.id}/messages") + |> json_response(403) + end + + test "GET /api/pleroma/admin/chats/:id", %{conn: conn, chat: chat} do + conn + |> get("/api/pleroma/admin/chats/#{chat.id}") + |> json_response(403) + end + end + + describe "unauthenticated chat moderation" do + setup do + user = insert(:user) + recipient = insert(:user) + + {:ok, message} = CommonAPI.post_chat_message(user, recipient, "Yo") + object = Object.normalize(message, false) + chat = Chat.get(user.id, recipient.ap_id) + cm_ref = MessageReference.for_chat_and_object(chat, object) + + %{conn: build_conn(), chat: chat, cm_ref: cm_ref} + end + + test "DELETE /api/pleroma/admin/chats/:id/messages/:message_id", %{ + conn: conn, + chat: chat, + cm_ref: cm_ref + } do + conn + |> put_req_header("content-type", "application/json") + |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") + |> json_response(403) + + assert MessageReference.get_by_id(cm_ref.id) == cm_ref + end + + test "GET /api/pleroma/admin/chats/:id/messages", %{conn: conn, chat: chat} do + conn + |> get("/api/pleroma/admin/chats/#{chat.id}/messages") + |> json_response(403) + end + + test "GET /api/pleroma/admin/chats/:id", %{conn: conn, chat: chat} do + conn + |> get("/api/pleroma/admin/chats/#{chat.id}") + |> json_response(403) + end + end +end diff --git a/test/web/admin_api/controllers/instance_document_controller_test.exs b/test/web/admin_api/controllers/instance_document_controller_test.exs @@ -0,0 +1,106 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.InstanceDocumentControllerTest do + use Pleroma.Web.ConnCase, async: true + import Pleroma.Factory + alias Pleroma.Config + + @dir "test/tmp/instance_static" + @default_instance_panel ~s(<p>Welcome to <a href="https://pleroma.social" target="_blank">Pleroma!</a></p>) + + setup do + File.mkdir_p!(@dir) + on_exit(fn -> File.rm_rf(@dir) end) + end + + setup do: clear_config([:instance, :static_dir], @dir) + + setup do + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + + {:ok, %{admin: admin, token: token, conn: conn}} + end + + describe "GET /api/pleroma/admin/instance_document/:name" do + test "return the instance document url", %{conn: conn} do + conn = get(conn, "/api/pleroma/admin/instance_document/instance-panel") + + assert content = html_response(conn, 200) + assert String.contains?(content, @default_instance_panel) + end + + test "it returns 403 if requested by a non-admin" do + non_admin_user = insert(:user) + token = insert(:oauth_token, user: non_admin_user) + + conn = + build_conn() + |> assign(:user, non_admin_user) + |> assign(:token, token) + |> get("/api/pleroma/admin/instance_document/instance-panel") + + assert json_response(conn, :forbidden) + end + + test "it returns 404 if the instance document with the given name doesn't exist", %{ + conn: conn + } do + conn = get(conn, "/api/pleroma/admin/instance_document/1234") + + assert json_response_and_validate_schema(conn, 404) + end + end + + describe "PATCH /api/pleroma/admin/instance_document/:name" do + test "uploads the instance document", %{conn: conn} do + image = %Plug.Upload{ + content_type: "text/html", + path: Path.absname("test/fixtures/custom_instance_panel.html"), + filename: "custom_instance_panel.html" + } + + conn = + conn + |> put_req_header("content-type", "multipart/form-data") + |> patch("/api/pleroma/admin/instance_document/instance-panel", %{ + "file" => image + }) + + assert %{"url" => url} = json_response_and_validate_schema(conn, 200) + index = get(build_conn(), url) + assert html_response(index, 200) == "<h2>Custom instance panel</h2>" + end + end + + describe "DELETE /api/pleroma/admin/instance_document/:name" do + test "deletes the instance document", %{conn: conn} do + File.mkdir!(@dir <> "/instance/") + File.write!(@dir <> "/instance/panel.html", "Custom instance panel") + + conn_resp = + conn + |> get("/api/pleroma/admin/instance_document/instance-panel") + + assert html_response(conn_resp, 200) == "Custom instance panel" + + conn + |> delete("/api/pleroma/admin/instance_document/instance-panel") + |> json_response_and_validate_schema(200) + + conn_resp = + conn + |> get("/api/pleroma/admin/instance_document/instance-panel") + + assert content = html_response(conn_resp, 200) + assert String.contains?(content, @default_instance_panel) + end + end +end diff --git a/test/web/admin_api/search_test.exs b/test/web/admin_api/search_test.exs @@ -177,5 +177,14 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do assert total == 3 assert count == 1 end + + test "it returns non-discoverable users" do + insert(:user) + insert(:user, discoverable: false) + + {:ok, _results, total} = Search.user() + + assert total == 2 + end end end diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs @@ -4,11 +4,14 @@ defmodule Pleroma.Web.CommonAPITest do use Pleroma.DataCase + use Oban.Testing, repo: Pleroma.Repo + alias Pleroma.Activity alias Pleroma.Chat alias Pleroma.Conversation.Participation alias Pleroma.Notification alias Pleroma.Object + alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Transmogrifier @@ -18,6 +21,7 @@ defmodule Pleroma.Web.CommonAPITest do import Pleroma.Factory import Mock + import Ecto.Query, only: [from: 2] require Pleroma.Constants @@ -607,15 +611,15 @@ defmodule Pleroma.Web.CommonAPITest do test "it can handle activities that expire" do user = insert(:user) - expires_at = - NaiveDateTime.utc_now() - |> NaiveDateTime.truncate(:second) - |> NaiveDateTime.add(1_000_000, :second) + expires_at = DateTime.add(DateTime.utc_now(), 1_000_000) assert {:ok, activity} = CommonAPI.post(user, %{status: "chai", expires_in: 1_000_000}) - assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id) - assert expiration.scheduled_at == expires_at + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity.id}, + scheduled_at: expires_at + ) end end @@ -819,6 +823,69 @@ defmodule Pleroma.Web.CommonAPITest do [user: user, activity: activity] end + test "marks notifications as read after mute" do + author = insert(:user) + activity = insert(:note_activity, user: author) + + friend1 = insert(:user) + friend2 = insert(:user) + + {:ok, reply_activity} = + CommonAPI.post( + friend2, + %{ + status: "@#{author.nickname} @#{friend1.nickname} test reply", + in_reply_to_status_id: activity.id + } + ) + + {:ok, favorite_activity} = CommonAPI.favorite(friend2, activity.id) + {:ok, repeat_activity} = CommonAPI.repeat(activity.id, friend1) + + assert Repo.aggregate( + from(n in Notification, where: n.seen == false and n.user_id == ^friend1.id), + :count + ) == 1 + + unread_notifications = + Repo.all(from(n in Notification, where: n.seen == false, where: n.user_id == ^author.id)) + + assert Enum.any?(unread_notifications, fn n -> + n.type == "favourite" && n.activity_id == favorite_activity.id + end) + + assert Enum.any?(unread_notifications, fn n -> + n.type == "reblog" && n.activity_id == repeat_activity.id + end) + + assert Enum.any?(unread_notifications, fn n -> + n.type == "mention" && n.activity_id == reply_activity.id + end) + + {:ok, _} = CommonAPI.add_mute(author, activity) + assert CommonAPI.thread_muted?(author, activity) + + assert Repo.aggregate( + from(n in Notification, where: n.seen == false and n.user_id == ^friend1.id), + :count + ) == 1 + + read_notifications = + Repo.all(from(n in Notification, where: n.seen == true, where: n.user_id == ^author.id)) + + assert Enum.any?(read_notifications, fn n -> + n.type == "favourite" && n.activity_id == favorite_activity.id + end) + + assert Enum.any?(read_notifications, fn n -> + n.type == "reblog" && n.activity_id == repeat_activity.id + end) + + assert Enum.any?(read_notifications, fn n -> + n.type == "mention" && n.activity_id == reply_activity.id + end) + end + test "add mute", %{user: user, activity: activity} do {:ok, _} = CommonAPI.add_mute(user, activity) assert CommonAPI.thread_muted?(user, activity) @@ -1137,4 +1204,24 @@ defmodule Pleroma.Web.CommonAPITest do assert Visibility.get_visibility(activity) == "private" end end + + describe "get_user/1" do + test "gets user by ap_id" do + user = insert(:user) + assert CommonAPI.get_user(user.ap_id) == user + end + + test "gets user by guessed nickname" do + user = insert(:user, ap_id: "", nickname: "mario@mushroom.kingdom") + assert CommonAPI.get_user("https://mushroom.kingdom/users/mario") == user + end + + test "fallback" do + assert %User{ + name: "", + ap_id: "", + nickname: "erroruser@example.com" + } = CommonAPI.get_user("") + end + end end diff --git a/test/web/fed_sockets/fed_registry_test.exs b/test/web/fed_sockets/fed_registry_test.exs @@ -0,0 +1,124 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.FedRegistryTest do + use ExUnit.Case + + alias Pleroma.Web.FedSockets + alias Pleroma.Web.FedSockets.FedRegistry + alias Pleroma.Web.FedSockets.SocketInfo + + @good_domain "http://good.domain" + @good_domain_origin "good.domain:80" + + setup do + start_supervised({Pleroma.Web.FedSockets.Supervisor, []}) + build_test_socket(@good_domain) + Process.sleep(10) + + :ok + end + + describe "add_fed_socket/1 without conflicting sockets" do + test "can be added" do + Process.sleep(10) + assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin) + assert origin == "good.domain:80" + end + + test "multiple origins can be added" do + build_test_socket("http://anothergood.domain") + Process.sleep(10) + + assert {:ok, %SocketInfo{origin: origin_1}} = + FedRegistry.get_fed_socket(@good_domain_origin) + + assert {:ok, %SocketInfo{origin: origin_2}} = + FedRegistry.get_fed_socket("anothergood.domain:80") + + assert origin_1 == "good.domain:80" + assert origin_2 == "anothergood.domain:80" + assert FedRegistry.list_all() |> Enum.count() == 2 + end + end + + describe "add_fed_socket/1 when duplicate sockets conflict" do + setup do + build_test_socket(@good_domain) + build_test_socket(@good_domain) + Process.sleep(10) + :ok + end + + test "will be ignored" do + assert {:ok, %SocketInfo{origin: origin, pid: pid_one}} = + FedRegistry.get_fed_socket(@good_domain_origin) + + assert origin == "good.domain:80" + + assert FedRegistry.list_all() |> Enum.count() == 1 + end + + test "the newer process will be closed" do + pid_two = build_test_socket(@good_domain) + + assert {:ok, %SocketInfo{origin: origin, pid: pid_one}} = + FedRegistry.get_fed_socket(@good_domain_origin) + + assert origin == "good.domain:80" + Process.sleep(10) + + refute Process.alive?(pid_two) + + assert FedRegistry.list_all() |> Enum.count() == 1 + end + end + + describe "get_fed_socket/1" do + test "returns missing for unknown hosts" do + assert {:error, :missing} = FedRegistry.get_fed_socket("not_a_dmoain") + end + + test "returns rejected for hosts previously rejected" do + "rejected.domain:80" + |> FedSockets.uri_for_origin() + |> FedRegistry.set_host_rejected() + + assert {:error, :rejected} = FedRegistry.get_fed_socket("rejected.domain:80") + end + + test "can retrieve a previously added SocketInfo" do + build_test_socket(@good_domain) + Process.sleep(10) + assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin) + assert origin == "good.domain:80" + end + + test "removes references to SocketInfos when the process crashes" do + assert {:ok, %SocketInfo{origin: origin, pid: pid}} = + FedRegistry.get_fed_socket(@good_domain_origin) + + assert origin == "good.domain:80" + + Process.exit(pid, :testing) + Process.sleep(100) + assert {:error, :missing} = FedRegistry.get_fed_socket(@good_domain_origin) + end + end + + def build_test_socket(uri) do + Kernel.spawn(fn -> fed_socket_almost(uri) end) + end + + def fed_socket_almost(origin) do + FedRegistry.add_fed_socket(origin) + + receive do + :close -> + :ok + after + 5_000 -> :timeout + end + end +end diff --git a/test/web/fed_sockets/fetch_registry_test.exs b/test/web/fed_sockets/fetch_registry_test.exs @@ -0,0 +1,67 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.FetchRegistryTest do + use ExUnit.Case + + alias Pleroma.Web.FedSockets.FetchRegistry + alias Pleroma.Web.FedSockets.FetchRegistry.FetchRegistryData + + @json_message "hello" + @json_reply "hello back" + + setup do + start_supervised( + {Pleroma.Web.FedSockets.Supervisor, + [ + ping_interval: 8, + connection_duration: 15, + rejection_duration: 5, + fed_socket_fetches: [default: 10, interval: 10] + ]} + ) + + :ok + end + + test "fetches can be stored" do + uuid = FetchRegistry.register_fetch(@json_message) + + assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) + end + + test "fetches can return" do + uuid = FetchRegistry.register_fetch(@json_message) + task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end) + + assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) + Task.await(task) + + assert {:ok, %FetchRegistryData{received_json: received_json}} = + FetchRegistry.check_fetch(uuid) + + assert received_json == @json_reply + end + + test "fetches are deleted once popped from stack" do + uuid = FetchRegistry.register_fetch(@json_message) + task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end) + Task.await(task) + + assert {:ok, %FetchRegistryData{received_json: received_json}} = + FetchRegistry.check_fetch(uuid) + + assert received_json == @json_reply + assert {:ok, @json_reply} = FetchRegistry.pop_fetch(uuid) + + assert {:error, :missing} = FetchRegistry.check_fetch(uuid) + end + + test "fetches can time out" do + uuid = FetchRegistry.register_fetch(@json_message) + assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) + Process.sleep(500) + assert {:error, :missing} = FetchRegistry.check_fetch(uuid) + end +end diff --git a/test/web/fed_sockets/socket_info_test.exs b/test/web/fed_sockets/socket_info_test.exs @@ -0,0 +1,118 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.SocketInfoTest do + use ExUnit.Case + + alias Pleroma.Web.FedSockets + alias Pleroma.Web.FedSockets.SocketInfo + + describe "uri_for_origin" do + test "provides the fed_socket URL given the origin information" do + endpoint = "example.com:4000" + assert FedSockets.uri_for_origin(endpoint) =~ "ws://" + assert FedSockets.uri_for_origin(endpoint) =~ endpoint + end + end + + describe "origin" do + test "will provide the origin field given a url" do + endpoint = "example.com:4000" + assert SocketInfo.origin("ws://#{endpoint}") == endpoint + assert SocketInfo.origin("http://#{endpoint}") == endpoint + assert SocketInfo.origin("https://#{endpoint}") == endpoint + end + + test "will proide the origin field given a uri" do + endpoint = "example.com:4000" + uri = URI.parse("http://#{endpoint}") + + assert SocketInfo.origin(uri) == endpoint + end + end + + describe "touch" do + test "will update the TTL" do + endpoint = "example.com:4000" + socket = SocketInfo.build("ws://#{endpoint}") + Process.sleep(2) + touched_socket = SocketInfo.touch(socket) + + assert socket.connected_until < touched_socket.connected_until + end + end + + describe "expired?" do + setup do + start_supervised( + {Pleroma.Web.FedSockets.Supervisor, + [ + ping_interval: 8, + connection_duration: 5, + rejection_duration: 5, + fed_socket_rejections: [lazy: true] + ]} + ) + + :ok + end + + test "tests if the TTL is exceeded" do + endpoint = "example.com:4000" + socket = SocketInfo.build("ws://#{endpoint}") + refute SocketInfo.expired?(socket) + Process.sleep(10) + + assert SocketInfo.expired?(socket) + end + end + + describe "creating outgoing connection records" do + test "can be passed a string" do + assert %{conn_pid: :pid, origin: _origin} = SocketInfo.build("example.com:4000", :pid) + end + + test "can be passed a URI" do + uri = URI.parse("http://example.com:4000") + assert %{conn_pid: :pid, origin: origin} = SocketInfo.build(uri, :pid) + assert origin =~ "example.com:4000" + end + + test "will include the port number" do + assert %{conn_pid: :pid, origin: origin} = SocketInfo.build("http://example.com:4000", :pid) + + assert origin =~ ":4000" + end + + test "will provide the port if missing" do + assert %{conn_pid: :pid, origin: "example.com:80"} = + SocketInfo.build("http://example.com", :pid) + + assert %{conn_pid: :pid, origin: "example.com:443"} = + SocketInfo.build("https://example.com", :pid) + end + end + + describe "creating incoming connection records" do + test "can be passed a string" do + assert %{pid: _, origin: _origin} = SocketInfo.build("example.com:4000") + end + + test "can be passed a URI" do + uri = URI.parse("example.com:4000") + assert %{pid: _, origin: _origin} = SocketInfo.build(uri) + end + + test "will include the port number" do + assert %{pid: _, origin: origin} = SocketInfo.build("http://example.com:4000") + + assert origin =~ ":4000" + end + + test "will provide the port if missing" do + assert %{pid: _, origin: "example.com:80"} = SocketInfo.build("http://example.com") + assert %{pid: _, origin: "example.com:443"} = SocketInfo.build("https://example.com") + end + end +end diff --git a/test/web/instances/instance_test.exs b/test/web/instances/instance_test.exs @@ -99,37 +99,54 @@ defmodule Pleroma.Instances.InstanceTest do end end - test "Scrapes favicon URLs" do - Tesla.Mock.mock(fn %{url: "https://favicon.example.org/"} -> - %Tesla.Env{ - status: 200, - body: ~s[<html><head><link rel="icon" href="/favicon.png"></head></html>] - } - end) - - assert "https://favicon.example.org/favicon.png" == - Instance.get_or_update_favicon(URI.parse("https://favicon.example.org/")) - end + describe "get_or_update_favicon/1" do + test "Scrapes favicon URLs" do + Tesla.Mock.mock(fn %{url: "https://favicon.example.org/"} -> + %Tesla.Env{ + status: 200, + body: ~s[<html><head><link rel="icon" href="/favicon.png"></head></html>] + } + end) + + assert "https://favicon.example.org/favicon.png" == + Instance.get_or_update_favicon(URI.parse("https://favicon.example.org/")) + end - test "Returns nil on too long favicon URLs" do - clear_config([:instances_favicons, :enabled], true) - - long_favicon_url = - "https://Lorem.ipsum.dolor.sit.amet/consecteturadipiscingelit/Praesentpharetrapurusutaliquamtempus/Mauriseulaoreetarcu/atfacilisisorci/Nullamporttitor/nequesedfeugiatmollis/dolormagnaefficiturlorem/nonpretiumsapienorcieurisus/Nullamveleratsem/Maecenassedaccumsanexnam/favicon.png" - - Tesla.Mock.mock(fn %{url: "https://long-favicon.example.org/"} -> - %Tesla.Env{ - status: 200, - body: ~s[<html><head><link rel="icon" href="] <> long_favicon_url <> ~s["></head></html>] - } - end) - - assert capture_log(fn -> - assert nil == - Instance.get_or_update_favicon( - URI.parse("https://long-favicon.example.org/") - ) - end) =~ - "Instance.get_or_update_favicon(\"long-favicon.example.org\") error: %Postgrex.Error{" + test "Returns nil on too long favicon URLs" do + long_favicon_url = + "https://Lorem.ipsum.dolor.sit.amet/consecteturadipiscingelit/Praesentpharetrapurusutaliquamtempus/Mauriseulaoreetarcu/atfacilisisorci/Nullamporttitor/nequesedfeugiatmollis/dolormagnaefficiturlorem/nonpretiumsapienorcieurisus/Nullamveleratsem/Maecenassedaccumsanexnam/favicon.png" + + Tesla.Mock.mock(fn %{url: "https://long-favicon.example.org/"} -> + %Tesla.Env{ + status: 200, + body: + ~s[<html><head><link rel="icon" href="] <> long_favicon_url <> ~s["></head></html>] + } + end) + + assert capture_log(fn -> + assert nil == + Instance.get_or_update_favicon( + URI.parse("https://long-favicon.example.org/") + ) + end) =~ + "Instance.get_or_update_favicon(\"long-favicon.example.org\") error: %Postgrex.Error{" + end + + test "Handles not getting a favicon URL properly" do + Tesla.Mock.mock(fn %{url: "https://no-favicon.example.org/"} -> + %Tesla.Env{ + status: 200, + body: ~s[<html><head><h1>I wil look down and whisper "GNO.."</h1></head></html>] + } + end) + + refute capture_log(fn -> + assert nil == + Instance.get_or_update_favicon( + URI.parse("https://no-favicon.example.org/") + ) + end) =~ "Instance.scrape_favicon(\"https://no-favicon.example.org/\") error: " + end end end diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -1442,7 +1442,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do describe "verify_credentials" do test "verify_credentials" do %{user: user, conn: conn} = oauth_access(["read:accounts"]) - [notification | _] = insert_list(7, :notification, user: user) + + [notification | _] = + insert_list(7, :notification, user: user, activity: insert(:note_activity)) + Pleroma.Notification.set_read_up_to(user, notification.id) conn = get(conn, "/api/v1/accounts/verify_credentials") diff --git a/test/web/mastodon_api/controllers/list_controller_test.exs b/test/web/mastodon_api/controllers/list_controller_test.exs @@ -67,7 +67,7 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do assert following == [other_user.follower_address] end - test "removing users from a list" do + test "removing users from a list, body params" do %{user: user, conn: conn} = oauth_access(["write:lists"]) other_user = insert(:user) third_user = insert(:user) @@ -85,6 +85,24 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do assert following == [third_user.follower_address] end + test "removing users from a list, query params" do + %{user: user, conn: conn} = oauth_access(["write:lists"]) + other_user = insert(:user) + third_user = insert(:user) + {:ok, list} = Pleroma.List.create("name", user) + {:ok, list} = Pleroma.List.follow(list, other_user) + {:ok, list} = Pleroma.List.follow(list, third_user) + + assert %{} == + conn + |> put_req_header("content-type", "application/json") + |> delete("/api/v1/lists/#{list.id}/accounts?account_ids[]=#{other_user.id}") + |> json_response_and_validate_schema(:ok) + + %Pleroma.List{following: following} = Pleroma.List.get(list.id, user) + assert following == [third_user.follower_address] + end + test "listing users in a list" do %{user: user, conn: conn} = oauth_access(["read:lists"]) other_user = insert(:user) diff --git a/test/web/mastodon_api/controllers/marker_controller_test.exs b/test/web/mastodon_api/controllers/marker_controller_test.exs @@ -11,7 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do test "gets markers with correct scopes", %{conn: conn} do user = insert(:user) token = insert(:oauth_token, user: user, scopes: ["read:statuses"]) - insert_list(7, :notification, user: user) + insert_list(7, :notification, user: user, activity: insert(:note_activity)) {:ok, %{"notifications" => marker}} = Pleroma.Marker.upsert( diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs @@ -282,18 +282,18 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do capture_log(fn -> {:ok, %{id: activity_id}} = CommonAPI.post(insert(:user), %{ - status: "check out https://shitposter.club/notice/2827873" + status: "check out http://mastodon.example.org/@admin/99541947525187367" }) results = conn - |> get("/api/v1/search?q=https://shitposter.club/notice/2827873") + |> get("/api/v1/search?q=http://mastodon.example.org/@admin/99541947525187367") |> json_response_and_validate_schema(200) - [status, %{"id" => ^activity_id}] = results["statuses"] - - assert status["uri"] == - "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" + assert [ + %{"url" => "http://mastodon.example.org/@admin/99541947525187367"}, + %{"id" => ^activity_id} + ] = results["statuses"] end) end diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -4,9 +4,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do use Pleroma.Web.ConnCase + use Oban.Testing, repo: Pleroma.Repo alias Pleroma.Activity - alias Pleroma.ActivityExpiration alias Pleroma.Config alias Pleroma.Conversation.Participation alias Pleroma.Object @@ -29,8 +29,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do setup do: oauth_access(["write:statuses"]) test "posting a status does not increment reblog_count when relaying", %{conn: conn} do - Pleroma.Config.put([:instance, :federating], true) - Pleroma.Config.get([:instance, :allow_relay], true) + Config.put([:instance, :federating], true) + Config.get([:instance, :allow_relay], true) response = conn @@ -103,7 +103,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do # An activity that will expire: # 2 hours - expires_in = 120 * 60 + expires_in = 2 * 60 * 60 + + expires_at = DateTime.add(DateTime.utc_now(), expires_in) conn_four = conn @@ -113,29 +115,22 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do "expires_in" => expires_in }) - assert fourth_response = - %{"id" => fourth_id} = json_response_and_validate_schema(conn_four, 200) - - assert activity = Activity.get_by_id(fourth_id) - assert expiration = ActivityExpiration.get_by_activity_id(fourth_id) - - estimated_expires_at = - NaiveDateTime.utc_now() - |> NaiveDateTime.add(expires_in) - |> NaiveDateTime.truncate(:second) + assert %{"id" => fourth_id} = json_response_and_validate_schema(conn_four, 200) - # This assert will fail if the test takes longer than a minute. I sure hope it never does: - assert abs(NaiveDateTime.diff(expiration.scheduled_at, estimated_expires_at, :second)) < 60 + assert Activity.get_by_id(fourth_id) - assert fourth_response["pleroma"]["expires_at"] == - NaiveDateTime.to_iso8601(expiration.scheduled_at) + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: fourth_id}, + scheduled_at: expires_at + ) end test "it fails to create a status if `expires_in` is less or equal than an hour", %{ conn: conn } do - # 1 hour - expires_in = 60 * 60 + # 1 minute + expires_in = 1 * 60 assert %{"error" => "Expiry date is too soon"} = conn @@ -146,8 +141,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do }) |> json_response_and_validate_schema(422) - # 30 minutes - expires_in = 30 * 60 + # 5 minutes + expires_in = 5 * 60 assert %{"error" => "Expiry date is too soon"} = conn @@ -160,8 +155,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do end test "Get MRF reason when posting a status is rejected by one", %{conn: conn} do - Pleroma.Config.put([:mrf_keyword, :reject], ["GNO"]) - Pleroma.Config.put([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) + Config.put([:mrf_keyword, :reject], ["GNO"]) + Config.put([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} = conn @@ -1146,6 +1141,52 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do |> post("/api/v1/statuses/#{activity_two.id}/pin") |> json_response_and_validate_schema(400) end + + test "on pin removes deletion job, on unpin reschedule deletion" do + %{conn: conn} = oauth_access(["write:accounts", "write:statuses"]) + expires_in = 2 * 60 * 60 + + expires_at = DateTime.add(DateTime.utc_now(), expires_in) + + assert %{"id" => id} = + conn + |> put_req_header("content-type", "application/json") + |> post("api/v1/statuses", %{ + "status" => "oolong", + "expires_in" => expires_in + }) + |> json_response_and_validate_schema(200) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: id}, + scheduled_at: expires_at + ) + + assert %{"id" => ^id, "pinned" => true} = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{id}/pin") + |> json_response_and_validate_schema(200) + + refute_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: id}, + scheduled_at: expires_at + ) + + assert %{"id" => ^id, "pinned" => false} = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{id}/unpin") + |> json_response_and_validate_schema(200) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: id}, + scheduled_at: expires_at + ) + end end describe "cards" do @@ -1681,19 +1722,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do test "expires_at is nil for another user" do %{conn: conn, user: user} = oauth_access(["read:statuses"]) + expires_at = DateTime.add(DateTime.utc_now(), 1_000_000) {:ok, activity} = CommonAPI.post(user, %{status: "foobar", expires_in: 1_000_000}) - expires_at = - activity.id - |> ActivityExpiration.get_by_activity_id() - |> Map.get(:scheduled_at) - |> NaiveDateTime.to_iso8601() - - assert %{"pleroma" => %{"expires_at" => ^expires_at}} = + assert %{"pleroma" => %{"expires_at" => a_expires_at}} = conn |> get("/api/v1/statuses/#{activity.id}") |> json_response_and_validate_schema(:ok) + {:ok, a_expires_at, 0} = DateTime.from_iso8601(a_expires_at) + assert DateTime.diff(expires_at, a_expires_at) == 0 + %{conn: conn} = oauth_access(["read:statuses"]) assert %{"pleroma" => %{"expires_at" => nil}} = diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -114,8 +114,16 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do {:ok, _reply_from_friend} = CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee}) - res_conn = get(conn, "/api/v1/timelines/public") - [%{"id" => ^activity_id}] = json_response_and_validate_schema(res_conn, 200) + # Still shows replies from yourself + {:ok, %{id: reply_from_me}} = + CommonAPI.post(blocker, %{status: "status", in_reply_to_status_id: reply_from_blockee}) + + response = + get(conn, "/api/v1/timelines/public") + |> json_response_and_validate_schema(200) + + assert length(response) == 2 + [%{"id" => ^reply_from_me}, %{"id" => ^activity_id}] = response end test "doesn't return replies if follow is posting with users from blocked domain" do diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs @@ -5,6 +5,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do use Pleroma.DataCase + alias Pleroma.Config alias Pleroma.User alias Pleroma.UserRelationship alias Pleroma.Web.CommonAPI @@ -68,7 +69,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do sensitive: false, pleroma: %{ actor_type: "Person", - discoverable: false + discoverable: true }, fields: [] }, @@ -116,9 +117,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end end - test "Favicon when :instance_favicons is enabled" do - end - test "Represent the user account for the account owner" do user = insert(:user) @@ -169,7 +167,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do sensitive: false, pleroma: %{ actor_type: "Service", - discoverable: false + discoverable: true }, fields: [] }, @@ -451,7 +449,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do test "shows unread_count only to the account owner" do user = insert(:user) - insert_list(7, :notification, user: user) + insert_list(7, :notification, user: user, activity: insert(:note_activity)) other_user = insert(:user) user = User.get_cached_by_ap_id(user.ap_id) @@ -543,8 +541,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end end - test "uses mediaproxy urls when it's enabled" do + test "uses mediaproxy urls when it's enabled (regardless of media preview proxy state)" do clear_config([:media_proxy, :enabled], true) + clear_config([:media_preview_proxy, :enabled]) user = insert(:user, @@ -553,20 +552,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do emoji: %{"joker_smile" => "https://evil.website/society.png"} ) - AccountView.render("show.json", %{user: user, skip_visibility_check: true}) - |> Enum.all?(fn - {key, url} when key in [:avatar, :avatar_static, :header, :header_static] -> - String.starts_with?(url, Pleroma.Web.base_url()) - - {:emojis, emojis} -> - Enum.all?(emojis, fn %{url: url, static_url: static_url} -> - String.starts_with?(url, Pleroma.Web.base_url()) && - String.starts_with?(static_url, Pleroma.Web.base_url()) - end) - - _ -> - true - end) - |> assert() + with media_preview_enabled <- [false, true] do + Config.put([:media_preview_proxy, :enabled], media_preview_enabled) + + AccountView.render("show.json", %{user: user, skip_visibility_check: true}) + |> Enum.all?(fn + {key, url} when key in [:avatar, :avatar_static, :header, :header_static] -> + String.starts_with?(url, Pleroma.Web.base_url()) + + {:emojis, emojis} -> + Enum.all?(emojis, fn %{url: url, static_url: static_url} -> + String.starts_with?(url, Pleroma.Web.base_url()) && + String.starts_with?(static_url, Pleroma.Web.base_url()) + end) + + _ -> + true + end) + |> assert() + end end end diff --git a/test/web/media_proxy/media_proxy_controller_test.exs b/test/web/media_proxy/media_proxy_controller_test.exs @@ -8,34 +8,34 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do import Mock alias Pleroma.Web.MediaProxy - alias Pleroma.Web.MediaProxy.MediaProxyController alias Plug.Conn setup do on_exit(fn -> Cachex.clear(:banned_urls_cache) end) end - test "it returns 404 when MediaProxy disabled", %{conn: conn} do - clear_config([:media_proxy, :enabled], false) - - assert %Conn{ - status: 404, - resp_body: "Not Found" - } = get(conn, "/proxy/hhgfh/eeeee") - - assert %Conn{ - status: 404, - resp_body: "Not Found" - } = get(conn, "/proxy/hhgfh/eeee/fff") - end - - describe "" do + describe "Media Proxy" do setup do clear_config([:media_proxy, :enabled], true) clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") + [url: MediaProxy.encode_url("https://google.fn/test.png")] end + test "it returns 404 when disabled", %{conn: conn} do + clear_config([:media_proxy, :enabled], false) + + assert %Conn{ + status: 404, + resp_body: "Not Found" + } = get(conn, "/proxy/hhgfh/eeeee") + + assert %Conn{ + status: 404, + resp_body: "Not Found" + } = get(conn, "/proxy/hhgfh/eeee/fff") + end + test "it returns 403 for invalid signature", %{conn: conn, url: url} do Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000") %{path: path} = URI.parse(url) @@ -56,7 +56,7 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do } = get(conn, "/proxy/hhgfh/eeee/fff") end - test "redirects on valid url when filename is invalidated", %{conn: conn, url: url} do + test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do invalid_url = String.replace(url, "test.png", "test-file.png") response = get(conn, invalid_url) assert response.status == 302 @@ -80,42 +80,248 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do end end - describe "filename_matches/3" do - test "preserves the encoded or decoded path" do - assert MediaProxyController.filename_matches( - %{"filename" => "/Hello world.jpg"}, - "/Hello world.jpg", - "http://pleroma.social/Hello world.jpg" - ) == :ok - - assert MediaProxyController.filename_matches( - %{"filename" => "/Hello%20world.jpg"}, - "/Hello%20world.jpg", - "http://pleroma.social/Hello%20world.jpg" - ) == :ok - - assert MediaProxyController.filename_matches( - %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"}, - "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", - "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg" - ) == :ok - - assert MediaProxyController.filename_matches( - %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jp"}, - "/my%2Flong%2Furl%2F2019%2F07%2FS.jp", - "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg" - ) == {:wrong_filename, "my%2Flong%2Furl%2F2019%2F07%2FS.jpg"} - end - - test "encoded url are tried to match for proxy as `conn.request_path` encodes the url" do - # conn.request_path will return encoded url - request_path = "/ANALYSE-DAI-_-LE-STABLECOIN-100-D%C3%89CENTRALIS%C3%89-BQ.jpg" - - assert MediaProxyController.filename_matches( - true, - request_path, - "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg" - ) == :ok + describe "Media Preview Proxy" do + setup do + clear_config([:media_proxy, :enabled], true) + clear_config([:media_preview_proxy, :enabled], true) + clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") + + original_url = "https://google.fn/test.png" + + [ + url: MediaProxy.encode_preview_url(original_url), + media_proxy_url: MediaProxy.encode_url(original_url) + ] + end + + test "returns 404 when media proxy is disabled", %{conn: conn} do + clear_config([:media_proxy, :enabled], false) + + assert %Conn{ + status: 404, + resp_body: "Not Found" + } = get(conn, "/proxy/preview/hhgfh/eeeee") + + assert %Conn{ + status: 404, + resp_body: "Not Found" + } = get(conn, "/proxy/preview/hhgfh/fff") + end + + test "returns 404 when disabled", %{conn: conn} do + clear_config([:media_preview_proxy, :enabled], false) + + assert %Conn{ + status: 404, + resp_body: "Not Found" + } = get(conn, "/proxy/preview/hhgfh/eeeee") + + assert %Conn{ + status: 404, + resp_body: "Not Found" + } = get(conn, "/proxy/preview/hhgfh/fff") + end + + test "it returns 403 for invalid signature", %{conn: conn, url: url} do + Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000") + %{path: path} = URI.parse(url) + + assert %Conn{ + status: 403, + resp_body: "Forbidden" + } = get(conn, path) + + assert %Conn{ + status: 403, + resp_body: "Forbidden" + } = get(conn, "/proxy/preview/hhgfh/eeee") + + assert %Conn{ + status: 403, + resp_body: "Forbidden" + } = get(conn, "/proxy/preview/hhgfh/eeee/fff") + end + + test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do + invalid_url = String.replace(url, "test.png", "test-file.png") + response = get(conn, invalid_url) + assert response.status == 302 + assert redirected_to(response) == url + end + + test "responds with 424 Failed Dependency if HEAD request to media proxy fails", %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{status: 500, body: ""} + end) + + response = get(conn, url) + assert response.status == 424 + assert response.resp_body == "Can't fetch HTTP headers (HTTP 500)." + end + + test "redirects to media proxy URI on unsupported content type", %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: "", headers: [{"content-type", "application/pdf"}]} + end) + + response = get(conn, url) + assert response.status == 302 + assert redirected_to(response) == media_proxy_url + end + + test "with `static=true` and GIF image preview requested, responds with JPEG image", %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + # Setting a high :min_content_length to ensure this scenario is not affected by its logic + clear_config([:media_preview_proxy, :min_content_length], 1_000_000_000) + + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{ + status: 200, + body: "", + headers: [{"content-type", "image/gif"}, {"content-length", "1001718"}] + } + + %{method: :get, url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.gif")} + end) + + response = get(conn, url <> "?static=true") + + assert response.status == 200 + assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"] + assert response.resp_body != "" + end + + test "with GIF image preview requested and no `static` param, redirects to media proxy URI", + %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/gif"}]} + end) + + response = get(conn, url) + + assert response.status == 302 + assert redirected_to(response) == media_proxy_url + end + + test "with `static` param and non-GIF image preview requested, " <> + "redirects to media preview proxy URI without `static` param", + %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} + end) + + response = get(conn, url <> "?static=true") + + assert response.status == 302 + assert redirected_to(response) == url + end + + test "with :min_content_length setting not matched by Content-Length header, " <> + "redirects to media proxy URI", + %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + clear_config([:media_preview_proxy, :min_content_length], 100_000) + + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{ + status: 200, + body: "", + headers: [{"content-type", "image/gif"}, {"content-length", "5000"}] + } + end) + + response = get(conn, url) + + assert response.status == 302 + assert redirected_to(response) == media_proxy_url + end + + test "thumbnails PNG images into PNG", %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/png"}]} + + %{method: :get, url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.png")} + end) + + response = get(conn, url) + + assert response.status == 200 + assert Conn.get_resp_header(response, "content-type") == ["image/png"] + assert response.resp_body != "" + end + + test "thumbnails JPEG images into JPEG", %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} + + %{method: :get, url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")} + end) + + response = get(conn, url) + + assert response.status == 200 + assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"] + assert response.resp_body != "" + end + + test "redirects to media proxy URI in case of thumbnailing error", %{ + conn: conn, + url: url, + media_proxy_url: media_proxy_url + } do + Tesla.Mock.mock(fn + %{method: "head", url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} + + %{method: :get, url: ^media_proxy_url} -> + %Tesla.Env{status: 200, body: "<html><body>error</body></html>"} + end) + + response = get(conn, url) + + assert response.status == 302 + assert redirected_to(response) == media_proxy_url end end end diff --git a/test/web/media_proxy/media_proxy_test.exs b/test/web/media_proxy/media_proxy_test.exs @@ -6,9 +6,16 @@ defmodule Pleroma.Web.MediaProxyTest do use ExUnit.Case use Pleroma.Tests.Helpers + alias Pleroma.Config alias Pleroma.Web.Endpoint alias Pleroma.Web.MediaProxy + defp decode_result(encoded) do + [_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/") + {:ok, decoded} = MediaProxy.decode_url(sig, base64) + decoded + end + describe "when enabled" do setup do: clear_config([:media_proxy, :enabled], true) @@ -35,7 +42,7 @@ defmodule Pleroma.Web.MediaProxyTest do assert String.starts_with?( encoded, - Pleroma.Config.get([:media_proxy, :base_url], Pleroma.Web.base_url()) + Config.get([:media_proxy, :base_url], Pleroma.Web.base_url()) ) assert String.ends_with?(encoded, "/logo.png") @@ -75,6 +82,64 @@ defmodule Pleroma.Web.MediaProxyTest do assert MediaProxy.decode_url(sig, base64) == {:error, :invalid_signature} end + def test_verify_request_path_and_url(request_path, url, expected_result) do + assert MediaProxy.verify_request_path_and_url(request_path, url) == expected_result + + assert MediaProxy.verify_request_path_and_url( + %Plug.Conn{ + params: %{"filename" => Path.basename(request_path)}, + request_path: request_path + }, + url + ) == expected_result + end + + test "if first arg of `verify_request_path_and_url/2` is a Plug.Conn without \"filename\" " <> + "parameter, `verify_request_path_and_url/2` returns :ok " do + assert MediaProxy.verify_request_path_and_url( + %Plug.Conn{params: %{}, request_path: "/some/path"}, + "https://instance.com/file.jpg" + ) == :ok + + assert MediaProxy.verify_request_path_and_url( + %Plug.Conn{params: %{}, request_path: "/path/to/file.jpg"}, + "https://instance.com/file.jpg" + ) == :ok + end + + test "`verify_request_path_and_url/2` preserves the encoded or decoded path" do + test_verify_request_path_and_url( + "/Hello world.jpg", + "http://pleroma.social/Hello world.jpg", + :ok + ) + + test_verify_request_path_and_url( + "/Hello%20world.jpg", + "http://pleroma.social/Hello%20world.jpg", + :ok + ) + + test_verify_request_path_and_url( + "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", + "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", + :ok + ) + + test_verify_request_path_and_url( + # Note: `conn.request_path` returns encoded url + "/ANALYSE-DAI-_-LE-STABLECOIN-100-D%C3%89CENTRALIS%C3%89-BQ.jpg", + "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg", + :ok + ) + + test_verify_request_path_and_url( + "/my%2Flong%2Furl%2F2019%2F07%2FS", + "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", + {:wrong_filename, "my%2Flong%2Furl%2F2019%2F07%2FS.jpg"} + ) + end + test "uses the configured base_url" do base_url = "https://cache.pleroma.social" clear_config([:media_proxy, :base_url], base_url) @@ -124,12 +189,6 @@ defmodule Pleroma.Web.MediaProxyTest do end end - defp decode_result(encoded) do - [_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/") - {:ok, decoded} = MediaProxy.decode_url(sig, base64) - decoded - end - describe "whitelist" do setup do: clear_config([:media_proxy, :enabled], true) diff --git a/test/web/metadata/metadata_test.exs b/test/web/metadata/metadata_test.exs @@ -16,7 +16,14 @@ defmodule Pleroma.Web.MetadataTest do end test "for local user" do - user = insert(:user) + user = insert(:user, discoverable: false) + + assert Pleroma.Web.Metadata.build_tags(%{user: user}) =~ + "<meta content=\"noindex, noarchive\" name=\"robots\">" + end + + test "for local user set to discoverable" do + user = insert(:user, discoverable: true) refute Pleroma.Web.Metadata.build_tags(%{user: user}) =~ "<meta content=\"noindex, noarchive\" name=\"robots\">" @@ -24,11 +31,19 @@ defmodule Pleroma.Web.MetadataTest do end describe "no metadata for private instances" do - test "for local user" do + test "for local user set to discoverable" do clear_config([:instance, :public], false) - user = insert(:user, bio: "This is my secret fedi account bio") + user = insert(:user, bio: "This is my secret fedi account bio", discoverable: true) assert "" = Pleroma.Web.Metadata.build_tags(%{user: user}) end + + test "search exclusion metadata is included" do + clear_config([:instance, :public], false) + user = insert(:user, bio: "This is my secret fedi account bio", discoverable: false) + + assert ~s(<meta content="noindex, noarchive" name="robots">) == + Pleroma.Web.Metadata.build_tags(%{user: user}) + end end end diff --git a/test/web/metadata/restrict_indexing_test.exs b/test/web/metadata/restrict_indexing_test.exs @@ -14,8 +14,14 @@ defmodule Pleroma.Web.Metadata.Providers.RestrictIndexingTest do test "for local user" do assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ - user: %Pleroma.User{local: true} + user: %Pleroma.User{local: true, discoverable: true} }) == [] end + + test "for local user when discoverable is false" do + assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ + user: %Pleroma.User{local: true, discoverable: false} + }) == [{:meta, [name: "robots", content: "noindex, noarchive"], []}] + end end end diff --git a/test/web/oauth/token_test.exs b/test/web/oauth/token_test.exs @@ -69,17 +69,4 @@ defmodule Pleroma.Web.OAuth.TokenTest do assert tokens == 2 end - - test "deletes expired tokens" do - insert(:oauth_token, valid_until: Timex.shift(Timex.now(), days: -3)) - insert(:oauth_token, valid_until: Timex.shift(Timex.now(), days: -3)) - t3 = insert(:oauth_token) - t4 = insert(:oauth_token, valid_until: Timex.shift(Timex.now(), minutes: 10)) - {tokens, _} = Token.delete_expired_tokens() - assert tokens == 2 - available_tokens = Pleroma.Repo.all(Token) - - token_ids = available_tokens |> Enum.map(& &1.id) - assert token_ids == [t3.id, t4.id] - end end diff --git a/test/web/pleroma_api/controllers/user_import_controller_test.exs b/test/web/pleroma_api/controllers/user_import_controller_test.exs @@ -0,0 +1,235 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do + use Pleroma.Web.ConnCase + use Oban.Testing, repo: Pleroma.Repo + + alias Pleroma.Config + alias Pleroma.Tests.ObanHelpers + + import Pleroma.Factory + import Mock + + setup do + Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) + :ok + end + + describe "POST /api/pleroma/follow_import" do + setup do: oauth_access(["follow"]) + + test "it returns HTTP 200", %{conn: conn} do + user2 = insert(:user) + + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"}) + |> json_response_and_validate_schema(200) + end + + test "it imports follow lists from file", %{conn: conn} do + user2 = insert(:user) + + with_mocks([ + {File, [], + read!: fn "follow_list.txt" -> + "Account address,Show boosts\n#{user2.ap_id},true" + end} + ]) do + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/follow_import", %{ + "list" => %Plug.Upload{path: "follow_list.txt"} + }) + |> json_response_and_validate_schema(200) + + assert [{:ok, job_result}] = ObanHelpers.perform_all() + assert job_result == [user2] + end + end + + test "it imports new-style mastodon follow lists", %{conn: conn} do + user2 = insert(:user) + + response = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/follow_import", %{ + "list" => "Account address,Show boosts\n#{user2.ap_id},true" + }) + |> json_response_and_validate_schema(200) + + assert response == "job started" + end + + test "requires 'follow' or 'write:follows' permissions" do + token1 = insert(:oauth_token, scopes: ["read", "write"]) + token2 = insert(:oauth_token, scopes: ["follow"]) + token3 = insert(:oauth_token, scopes: ["something"]) + another_user = insert(:user) + + for token <- [token1, token2, token3] do + conn = + build_conn() + |> put_req_header("authorization", "Bearer #{token.token}") + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"}) + + if token == token3 do + assert %{"error" => "Insufficient permissions: follow | write:follows."} == + json_response(conn, 403) + else + assert json_response(conn, 200) + end + end + end + + test "it imports follows with different nickname variations", %{conn: conn} do + users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + + identifiers = + [ + user2.ap_id, + user3.nickname, + " ", + "@" <> user4.nickname, + user5.nickname <> "@localhost", + "@" <> user6.nickname <> "@localhost" + ] + |> Enum.join("\n") + + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/follow_import", %{"list" => identifiers}) + |> json_response_and_validate_schema(200) + + assert [{:ok, job_result}] = ObanHelpers.perform_all() + assert job_result == users + end + end + + describe "POST /api/pleroma/blocks_import" do + # Note: "follow" or "write:blocks" permission is required + setup do: oauth_access(["write:blocks"]) + + test "it returns HTTP 200", %{conn: conn} do + user2 = insert(:user) + + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"}) + |> json_response_and_validate_schema(200) + end + + test "it imports blocks users from file", %{conn: conn} do + users = [user2, user3] = insert_list(2, :user) + + with_mocks([ + {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} + ]) do + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/blocks_import", %{ + "list" => %Plug.Upload{path: "blocks_list.txt"} + }) + |> json_response_and_validate_schema(200) + + assert [{:ok, job_result}] = ObanHelpers.perform_all() + assert job_result == users + end + end + + test "it imports blocks with different nickname variations", %{conn: conn} do + users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + + identifiers = + [ + user2.ap_id, + user3.nickname, + "@" <> user4.nickname, + user5.nickname <> "@localhost", + "@" <> user6.nickname <> "@localhost" + ] + |> Enum.join(" ") + + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/blocks_import", %{"list" => identifiers}) + |> json_response_and_validate_schema(200) + + assert [{:ok, job_result}] = ObanHelpers.perform_all() + assert job_result == users + end + end + + describe "POST /api/pleroma/mutes_import" do + # Note: "follow" or "write:mutes" permission is required + setup do: oauth_access(["write:mutes"]) + + test "it returns HTTP 200", %{user: user, conn: conn} do + user2 = insert(:user) + + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/mutes_import", %{"list" => "#{user2.ap_id}"}) + |> json_response_and_validate_schema(200) + + assert [{:ok, job_result}] = ObanHelpers.perform_all() + assert job_result == [user2] + assert Pleroma.User.mutes?(user, user2) + end + + test "it imports mutes users from file", %{user: user, conn: conn} do + users = [user2, user3] = insert_list(2, :user) + + with_mocks([ + {File, [], read!: fn "mutes_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} + ]) do + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/mutes_import", %{ + "list" => %Plug.Upload{path: "mutes_list.txt"} + }) + |> json_response_and_validate_schema(200) + + assert [{:ok, job_result}] = ObanHelpers.perform_all() + assert job_result == users + assert Enum.all?(users, &Pleroma.User.mutes?(user, &1)) + end + end + + test "it imports mutes with different nickname variations", %{user: user, conn: conn} do + users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + + identifiers = + [ + user2.ap_id, + user3.nickname, + "@" <> user4.nickname, + user5.nickname <> "@localhost", + "@" <> user6.nickname <> "@localhost" + ] + |> Enum.join(" ") + + assert "job started" == + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/mutes_import", %{"list" => identifiers}) + |> json_response_and_validate_schema(200) + + assert [{:ok, job_result}] = ObanHelpers.perform_all() + assert job_result == users + assert Enum.all?(users, &Pleroma.User.mutes?(user, &1)) + end + end +end diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs @@ -12,7 +12,9 @@ defmodule Pleroma.Web.Push.ImplTest do alias Pleroma.Web.CommonAPI alias Pleroma.Web.Push.Impl alias Pleroma.Web.Push.Subscription + alias Pleroma.Web.WebPushHttpClientMock + import Mock import Pleroma.Factory setup do @@ -78,6 +80,22 @@ defmodule Pleroma.Web.Push.ImplTest do assert Impl.push_message(@message, @sub, @api_key, %Subscription{}) == :ok end + test_with_mock "uses WebPushHttpClientMock as an HTTP client", WebPushHttpClientMock, + post: fn _, _, _ -> {:ok, %{status_code: 200}} end do + Impl.push_message(@message, @sub, @api_key, %Subscription{}) + assert_called(WebPushHttpClientMock.post("https://example.com/example/1234", :_, :_)) + end + + test_with_mock "uses Pleroma.HTTP as an HTTP client", Pleroma.HTTP, + post: fn _, _, _ -> {:ok, %{status_code: 200}} end do + client = Application.get_env(:web_push_encryption, :http_client) + on_exit(fn -> Application.put_env(:web_push_encryption, :http_client, client) end) + Application.put_env(:web_push_encryption, :http_client, Pleroma.HTTP) + + Impl.push_message(@message, @sub, @api_key, %Subscription{}) + assert_called(Pleroma.HTTP.post("https://example.com/example/1234", :_, :_)) + end + @tag capture_log: true test "fail message sending" do assert Impl.push_message( diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs @@ -87,9 +87,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do end test "doesn't just add a title" do - assert Parser.parse("http://example.com/non-ogp") == - {:error, - "Found metadata was invalid or incomplete: %{\"url\" => \"http://example.com/non-ogp\"}"} + assert {:error, {:invalid_metadata, _}} = Parser.parse("http://example.com/non-ogp") end test "parses ogp" do diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs @@ -21,92 +21,148 @@ defmodule Pleroma.Web.StreamerTest do setup do: clear_config([:instance, :skip_thread_containment]) - describe "get_topic without an user" do + describe "get_topic/_ (unauthenticated)" do test "allows public" do - assert {:ok, "public"} = Streamer.get_topic("public", nil) - assert {:ok, "public:local"} = Streamer.get_topic("public:local", nil) - assert {:ok, "public:media"} = Streamer.get_topic("public:media", nil) - assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil) + assert {:ok, "public"} = Streamer.get_topic("public", nil, nil) + assert {:ok, "public:local"} = Streamer.get_topic("public:local", nil, nil) + assert {:ok, "public:media"} = Streamer.get_topic("public:media", nil, nil) + assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil, nil) end test "allows hashtag streams" do - assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", nil, %{"tag" => "cofe"}) + assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", nil, nil, %{"tag" => "cofe"}) end test "disallows user streams" do - assert {:error, _} = Streamer.get_topic("user", nil) - assert {:error, _} = Streamer.get_topic("user:notification", nil) - assert {:error, _} = Streamer.get_topic("direct", nil) + assert {:error, _} = Streamer.get_topic("user", nil, nil) + assert {:error, _} = Streamer.get_topic("user:notification", nil, nil) + assert {:error, _} = Streamer.get_topic("direct", nil, nil) end test "disallows list streams" do - assert {:error, _} = Streamer.get_topic("list", nil, %{"list" => 42}) + assert {:error, _} = Streamer.get_topic("list", nil, nil, %{"list" => 42}) end end - describe "get_topic with an user" do - setup do - user = insert(:user) - {:ok, %{user: user}} - end + describe "get_topic/_ (authenticated)" do + setup do: oauth_access(["read"]) + + test "allows public streams (regardless of OAuth token scopes)", %{ + user: user, + token: read_oauth_token + } do + with oauth_token <- [nil, read_oauth_token] do + assert {:ok, "public"} = Streamer.get_topic("public", user, oauth_token) + assert {:ok, "public:local"} = Streamer.get_topic("public:local", user, oauth_token) + assert {:ok, "public:media"} = Streamer.get_topic("public:media", user, oauth_token) - test "allows public streams", %{user: user} do - assert {:ok, "public"} = Streamer.get_topic("public", user) - assert {:ok, "public:local"} = Streamer.get_topic("public:local", user) - assert {:ok, "public:media"} = Streamer.get_topic("public:media", user) - assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", user) + assert {:ok, "public:local:media"} = + Streamer.get_topic("public:local:media", user, oauth_token) + end end - test "allows user streams", %{user: user} do + test "allows user streams (with proper OAuth token scopes)", %{ + user: user, + token: read_oauth_token + } do + %{token: read_notifications_token} = oauth_access(["read:notifications"], user: user) + %{token: read_statuses_token} = oauth_access(["read:statuses"], user: user) + %{token: badly_scoped_token} = oauth_access(["irrelevant:scope"], user: user) + expected_user_topic = "user:#{user.id}" - expected_notif_topic = "user:notification:#{user.id}" + expected_notification_topic = "user:notification:#{user.id}" expected_direct_topic = "direct:#{user.id}" - assert {:ok, ^expected_user_topic} = Streamer.get_topic("user", user) - assert {:ok, ^expected_notif_topic} = Streamer.get_topic("user:notification", user) - assert {:ok, ^expected_direct_topic} = Streamer.get_topic("direct", user) + expected_pleroma_chat_topic = "user:pleroma_chat:#{user.id}" + + for valid_user_token <- [read_oauth_token, read_statuses_token] do + assert {:ok, ^expected_user_topic} = Streamer.get_topic("user", user, valid_user_token) + + assert {:ok, ^expected_direct_topic} = + Streamer.get_topic("direct", user, valid_user_token) + + assert {:ok, ^expected_pleroma_chat_topic} = + Streamer.get_topic("user:pleroma_chat", user, valid_user_token) + end + + for invalid_user_token <- [read_notifications_token, badly_scoped_token], + user_topic <- ["user", "direct", "user:pleroma_chat"] do + assert {:error, :unauthorized} = Streamer.get_topic(user_topic, user, invalid_user_token) + end + + for valid_notification_token <- [read_oauth_token, read_notifications_token] do + assert {:ok, ^expected_notification_topic} = + Streamer.get_topic("user:notification", user, valid_notification_token) + end + + for invalid_notification_token <- [read_statuses_token, badly_scoped_token] do + assert {:error, :unauthorized} = + Streamer.get_topic("user:notification", user, invalid_notification_token) + end end - test "allows hashtag streams", %{user: user} do - assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", user, %{"tag" => "cofe"}) + test "allows hashtag streams (regardless of OAuth token scopes)", %{ + user: user, + token: read_oauth_token + } do + for oauth_token <- [nil, read_oauth_token] do + assert {:ok, "hashtag:cofe"} = + Streamer.get_topic("hashtag", user, oauth_token, %{"tag" => "cofe"}) + end end - test "disallows registering to an user stream", %{user: user} do + test "disallows registering to another user's stream", %{user: user, token: read_oauth_token} do another_user = insert(:user) - assert {:error, _} = Streamer.get_topic("user:#{another_user.id}", user) - assert {:error, _} = Streamer.get_topic("user:notification:#{another_user.id}", user) - assert {:error, _} = Streamer.get_topic("direct:#{another_user.id}", user) + assert {:error, _} = Streamer.get_topic("user:#{another_user.id}", user, read_oauth_token) + + assert {:error, _} = + Streamer.get_topic("user:notification:#{another_user.id}", user, read_oauth_token) + + assert {:error, _} = Streamer.get_topic("direct:#{another_user.id}", user, read_oauth_token) end - test "allows list stream that are owned by the user", %{user: user} do + test "allows list stream that are owned by the user (with `read` or `read:lists` scopes)", %{ + user: user, + token: read_oauth_token + } do + %{token: read_lists_token} = oauth_access(["read:lists"], user: user) + %{token: invalid_token} = oauth_access(["irrelevant:scope"], user: user) {:ok, list} = List.create("Test", user) - assert {:error, _} = Streamer.get_topic("list:#{list.id}", user) - assert {:ok, _} = Streamer.get_topic("list", user, %{"list" => list.id}) + + assert {:error, _} = Streamer.get_topic("list:#{list.id}", user, read_oauth_token) + + for valid_token <- [read_oauth_token, read_lists_token] do + assert {:ok, _} = Streamer.get_topic("list", user, valid_token, %{"list" => list.id}) + end + + assert {:error, _} = Streamer.get_topic("list", user, invalid_token, %{"list" => list.id}) end - test "disallows list stream that are not owned by the user", %{user: user} do + test "disallows list stream that are not owned by the user", %{user: user, token: oauth_token} do another_user = insert(:user) {:ok, list} = List.create("Test", another_user) - assert {:error, _} = Streamer.get_topic("list:#{list.id}", user) - assert {:error, _} = Streamer.get_topic("list", user, %{"list" => list.id}) + + assert {:error, _} = Streamer.get_topic("list:#{list.id}", user, oauth_token) + assert {:error, _} = Streamer.get_topic("list", user, oauth_token, %{"list" => list.id}) end end describe "user streams" do setup do - user = insert(:user) + %{user: user, token: token} = oauth_access(["read"]) notify = insert(:notification, user: user, activity: build(:note_activity)) - {:ok, %{user: user, notify: notify}} + {:ok, %{user: user, notify: notify, token: token}} end - test "it streams the user's post in the 'user' stream", %{user: user} do - Streamer.get_topic_and_add_socket("user", user) + test "it streams the user's post in the 'user' stream", %{user: user, token: oauth_token} do + Streamer.get_topic_and_add_socket("user", user, oauth_token) {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) + assert_receive {:render_with_user, _, _, ^activity} refute Streamer.filtered_by_user?(user, activity) end - test "it streams boosts of the user in the 'user' stream", %{user: user} do - Streamer.get_topic_and_add_socket("user", user) + test "it streams boosts of the user in the 'user' stream", %{user: user, token: oauth_token} do + Streamer.get_topic_and_add_socket("user", user, oauth_token) other_user = insert(:user) {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) @@ -117,9 +173,10 @@ defmodule Pleroma.Web.StreamerTest do end test "it does not stream announces of the user's own posts in the 'user' stream", %{ - user: user + user: user, + token: oauth_token } do - Streamer.get_topic_and_add_socket("user", user) + Streamer.get_topic_and_add_socket("user", user, oauth_token) other_user = insert(:user) {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) @@ -129,9 +186,10 @@ defmodule Pleroma.Web.StreamerTest do end test "it does stream notifications announces of the user's own posts in the 'user' stream", %{ - user: user + user: user, + token: oauth_token } do - Streamer.get_topic_and_add_socket("user", user) + Streamer.get_topic_and_add_socket("user", user, oauth_token) other_user = insert(:user) {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) @@ -145,8 +203,11 @@ defmodule Pleroma.Web.StreamerTest do refute Streamer.filtered_by_user?(user, notification) end - test "it streams boosts of mastodon user in the 'user' stream", %{user: user} do - Streamer.get_topic_and_add_socket("user", user) + test "it streams boosts of mastodon user in the 'user' stream", %{ + user: user, + token: oauth_token + } do + Streamer.get_topic_and_add_socket("user", user, oauth_token) other_user = insert(:user) {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) @@ -164,21 +225,34 @@ defmodule Pleroma.Web.StreamerTest do refute Streamer.filtered_by_user?(user, announce) end - test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do - Streamer.get_topic_and_add_socket("user", user) + test "it sends notify to in the 'user' stream", %{ + user: user, + token: oauth_token, + notify: notify + } do + Streamer.get_topic_and_add_socket("user", user, oauth_token) Streamer.stream("user", notify) + assert_receive {:render_with_user, _, _, ^notify} refute Streamer.filtered_by_user?(user, notify) end - test "it sends notify to in the 'user:notification' stream", %{user: user, notify: notify} do - Streamer.get_topic_and_add_socket("user:notification", user) + test "it sends notify to in the 'user:notification' stream", %{ + user: user, + token: oauth_token, + notify: notify + } do + Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) Streamer.stream("user:notification", notify) + assert_receive {:render_with_user, _, _, ^notify} refute Streamer.filtered_by_user?(user, notify) end - test "it sends chat messages to the 'user:pleroma_chat' stream", %{user: user} do + test "it sends chat messages to the 'user:pleroma_chat' stream", %{ + user: user, + token: oauth_token + } do other_user = insert(:user) {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") @@ -187,7 +261,7 @@ defmodule Pleroma.Web.StreamerTest do cm_ref = MessageReference.for_chat_and_object(chat, object) cm_ref = %{cm_ref | chat: chat, object: object} - Streamer.get_topic_and_add_socket("user:pleroma_chat", user) + Streamer.get_topic_and_add_socket("user:pleroma_chat", user, oauth_token) Streamer.stream("user:pleroma_chat", {user, cm_ref}) text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}) @@ -196,7 +270,7 @@ defmodule Pleroma.Web.StreamerTest do assert_receive {:text, ^text} end - test "it sends chat messages to the 'user' stream", %{user: user} do + test "it sends chat messages to the 'user' stream", %{user: user, token: oauth_token} do other_user = insert(:user) {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") @@ -205,7 +279,7 @@ defmodule Pleroma.Web.StreamerTest do cm_ref = MessageReference.for_chat_and_object(chat, object) cm_ref = %{cm_ref | chat: chat, object: object} - Streamer.get_topic_and_add_socket("user", user) + Streamer.get_topic_and_add_socket("user", user, oauth_token) Streamer.stream("user", {user, cm_ref}) text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}) @@ -214,7 +288,10 @@ defmodule Pleroma.Web.StreamerTest do assert_receive {:text, ^text} end - test "it sends chat message notifications to the 'user:notification' stream", %{user: user} do + test "it sends chat message notifications to the 'user:notification' stream", %{ + user: user, + token: oauth_token + } do other_user = insert(:user) {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey") @@ -223,19 +300,21 @@ defmodule Pleroma.Web.StreamerTest do Repo.get_by(Pleroma.Notification, user_id: user.id, activity_id: create_activity.id) |> Repo.preload(:activity) - Streamer.get_topic_and_add_socket("user:notification", user) + Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) Streamer.stream("user:notification", notify) + assert_receive {:render_with_user, _, _, ^notify} refute Streamer.filtered_by_user?(user, notify) end test "it doesn't send notify to the 'user:notification' stream when a user is blocked", %{ - user: user + user: user, + token: oauth_token } do blocked = insert(:user) {:ok, _user_relationship} = User.block(user, blocked) - Streamer.get_topic_and_add_socket("user:notification", user) + Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) {:ok, activity} = CommonAPI.post(user, %{status: ":("}) {:ok, _} = CommonAPI.favorite(blocked, activity.id) @@ -244,14 +323,15 @@ defmodule Pleroma.Web.StreamerTest do end test "it doesn't send notify to the 'user:notification' stream when a thread is muted", %{ - user: user + user: user, + token: oauth_token } do user2 = insert(:user) {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) {:ok, _} = CommonAPI.add_mute(user, activity) - Streamer.get_topic_and_add_socket("user:notification", user) + Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id) @@ -260,12 +340,13 @@ defmodule Pleroma.Web.StreamerTest do end test "it sends favorite to 'user:notification' stream'", %{ - user: user + user: user, + token: oauth_token } do user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"}) {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) - Streamer.get_topic_and_add_socket("user:notification", user) + Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id) assert_receive {:render_with_user, _, "notification.json", notif} @@ -274,13 +355,14 @@ defmodule Pleroma.Web.StreamerTest do end test "it doesn't send the 'user:notification' stream' when a domain is blocked", %{ - user: user + user: user, + token: oauth_token } do user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"}) {:ok, user} = User.block_domain(user, "hecking-lewd-place.com") {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) - Streamer.get_topic_and_add_socket("user:notification", user) + Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id) refute_receive _ @@ -288,7 +370,8 @@ defmodule Pleroma.Web.StreamerTest do end test "it sends follow activities to the 'user:notification' stream", %{ - user: user + user: user, + token: oauth_token } do user_url = user.ap_id user2 = insert(:user) @@ -303,7 +386,7 @@ defmodule Pleroma.Web.StreamerTest do %Tesla.Env{status: 200, body: body} end) - Streamer.get_topic_and_add_socket("user:notification", user) + Streamer.get_topic_and_add_socket("user:notification", user, oauth_token) {:ok, _follower, _followed, follow_activity} = CommonAPI.follow(user2, user) assert_receive {:render_with_user, _, "notification.json", notif} @@ -312,51 +395,53 @@ defmodule Pleroma.Web.StreamerTest do end end - test "it sends to public authenticated" do - user = insert(:user) - other_user = insert(:user) + describe "public streams" do + test "it sends to public (authenticated)" do + %{user: user, token: oauth_token} = oauth_access(["read"]) + other_user = insert(:user) - Streamer.get_topic_and_add_socket("public", other_user) + Streamer.get_topic_and_add_socket("public", user, oauth_token) - {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) - assert_receive {:render_with_user, _, _, ^activity} - refute Streamer.filtered_by_user?(user, activity) - end + {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) + assert_receive {:render_with_user, _, _, ^activity} + refute Streamer.filtered_by_user?(other_user, activity) + end - test "works for deletions" do - user = insert(:user) - other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) + test "it sends to public (unauthenticated)" do + user = insert(:user) - Streamer.get_topic_and_add_socket("public", user) + Streamer.get_topic_and_add_socket("public", nil, nil) - {:ok, _} = CommonAPI.delete(activity.id, other_user) - activity_id = activity.id - assert_receive {:text, event} - assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) - end + {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) + activity_id = activity.id + assert_receive {:text, event} + assert %{"event" => "update", "payload" => payload} = Jason.decode!(event) + assert %{"id" => ^activity_id} = Jason.decode!(payload) - test "it sends to public unauthenticated" do - user = insert(:user) + {:ok, _} = CommonAPI.delete(activity.id, user) + assert_receive {:text, event} + assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) + end - Streamer.get_topic_and_add_socket("public", nil) + test "handles deletions" do + %{user: user, token: oauth_token} = oauth_access(["read"]) + other_user = insert(:user) + {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) - {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) - activity_id = activity.id - assert_receive {:text, event} - assert %{"event" => "update", "payload" => payload} = Jason.decode!(event) - assert %{"id" => ^activity_id} = Jason.decode!(payload) + Streamer.get_topic_and_add_socket("public", user, oauth_token) - {:ok, _} = CommonAPI.delete(activity.id, user) - assert_receive {:text, event} - assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) + {:ok, _} = CommonAPI.delete(activity.id, other_user) + activity_id = activity.id + assert_receive {:text, event} + assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) + end end - describe "thread_containment" do + describe "thread_containment/2" do test "it filters to user if recipients invalid and thread containment is enabled" do Pleroma.Config.put([:instance, :skip_thread_containment], false) author = insert(:user) - user = insert(:user) + %{user: user, token: oauth_token} = oauth_access(["read"]) User.follow(user, author, :follow_accept) activity = @@ -368,7 +453,7 @@ defmodule Pleroma.Web.StreamerTest do ) ) - Streamer.get_topic_and_add_socket("public", user) + Streamer.get_topic_and_add_socket("public", user, oauth_token) Streamer.stream("public", activity) assert_receive {:render_with_user, _, _, ^activity} assert Streamer.filtered_by_user?(user, activity) @@ -377,7 +462,7 @@ defmodule Pleroma.Web.StreamerTest do test "it sends message if recipients invalid and thread containment is disabled" do Pleroma.Config.put([:instance, :skip_thread_containment], true) author = insert(:user) - user = insert(:user) + %{user: user, token: oauth_token} = oauth_access(["read"]) User.follow(user, author, :follow_accept) activity = @@ -389,7 +474,7 @@ defmodule Pleroma.Web.StreamerTest do ) ) - Streamer.get_topic_and_add_socket("public", user) + Streamer.get_topic_and_add_socket("public", user, oauth_token) Streamer.stream("public", activity) assert_receive {:render_with_user, _, _, ^activity} @@ -400,6 +485,7 @@ defmodule Pleroma.Web.StreamerTest do Pleroma.Config.put([:instance, :skip_thread_containment], false) author = insert(:user) user = insert(:user, skip_thread_containment: true) + %{token: oauth_token} = oauth_access(["read"], user: user) User.follow(user, author, :follow_accept) activity = @@ -411,7 +497,7 @@ defmodule Pleroma.Web.StreamerTest do ) ) - Streamer.get_topic_and_add_socket("public", user) + Streamer.get_topic_and_add_socket("public", user, oauth_token) Streamer.stream("public", activity) assert_receive {:render_with_user, _, _, ^activity} @@ -420,23 +506,26 @@ defmodule Pleroma.Web.StreamerTest do end describe "blocks" do - test "it filters messages involving blocked users" do - user = insert(:user) + setup do: oauth_access(["read"]) + + test "it filters messages involving blocked users", %{user: user, token: oauth_token} do blocked_user = insert(:user) {:ok, _user_relationship} = User.block(user, blocked_user) - Streamer.get_topic_and_add_socket("public", user) + Streamer.get_topic_and_add_socket("public", user, oauth_token) {:ok, activity} = CommonAPI.post(blocked_user, %{status: "Test"}) assert_receive {:render_with_user, _, _, ^activity} assert Streamer.filtered_by_user?(user, activity) end - test "it filters messages transitively involving blocked users" do - blocker = insert(:user) + test "it filters messages transitively involving blocked users", %{ + user: blocker, + token: blocker_token + } do blockee = insert(:user) friend = insert(:user) - Streamer.get_topic_and_add_socket("public", blocker) + Streamer.get_topic_and_add_socket("public", blocker, blocker_token) {:ok, _user_relationship} = User.block(blocker, blockee) @@ -458,8 +547,9 @@ defmodule Pleroma.Web.StreamerTest do end describe "lists" do - test "it doesn't send unwanted DMs to list" do - user_a = insert(:user) + setup do: oauth_access(["read"]) + + test "it doesn't send unwanted DMs to list", %{user: user_a, token: user_a_token} do user_b = insert(:user) user_c = insert(:user) @@ -468,7 +558,7 @@ defmodule Pleroma.Web.StreamerTest do {:ok, list} = List.create("Test", user_a) {:ok, list} = List.follow(list, user_b) - Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) + Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id}) {:ok, _activity} = CommonAPI.post(user_b, %{ @@ -479,14 +569,13 @@ defmodule Pleroma.Web.StreamerTest do refute_receive _ end - test "it doesn't send unwanted private posts to list" do - user_a = insert(:user) + test "it doesn't send unwanted private posts to list", %{user: user_a, token: user_a_token} do user_b = insert(:user) {:ok, list} = List.create("Test", user_a) {:ok, list} = List.follow(list, user_b) - Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) + Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id}) {:ok, _activity} = CommonAPI.post(user_b, %{ @@ -497,8 +586,7 @@ defmodule Pleroma.Web.StreamerTest do refute_receive _ end - test "it sends wanted private posts to list" do - user_a = insert(:user) + test "it sends wanted private posts to list", %{user: user_a, token: user_a_token} do user_b = insert(:user) {:ok, user_a} = User.follow(user_a, user_b) @@ -506,7 +594,7 @@ defmodule Pleroma.Web.StreamerTest do {:ok, list} = List.create("Test", user_a) {:ok, list} = List.follow(list, user_b) - Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) + Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id}) {:ok, activity} = CommonAPI.post(user_b, %{ @@ -520,8 +608,9 @@ defmodule Pleroma.Web.StreamerTest do end describe "muted reblogs" do - test "it filters muted reblogs" do - user1 = insert(:user) + setup do: oauth_access(["read"]) + + test "it filters muted reblogs", %{user: user1, token: user1_token} do user2 = insert(:user) user3 = insert(:user) CommonAPI.follow(user1, user2) @@ -529,34 +618,38 @@ defmodule Pleroma.Web.StreamerTest do {:ok, create_activity} = CommonAPI.post(user3, %{status: "I'm kawen"}) - Streamer.get_topic_and_add_socket("user", user1) + Streamer.get_topic_and_add_socket("user", user1, user1_token) {:ok, announce_activity} = CommonAPI.repeat(create_activity.id, user2) assert_receive {:render_with_user, _, _, ^announce_activity} assert Streamer.filtered_by_user?(user1, announce_activity) end - test "it filters reblog notification for reblog-muted actors" do - user1 = insert(:user) + test "it filters reblog notification for reblog-muted actors", %{ + user: user1, + token: user1_token + } do user2 = insert(:user) CommonAPI.follow(user1, user2) CommonAPI.hide_reblogs(user1, user2) {:ok, create_activity} = CommonAPI.post(user1, %{status: "I'm kawen"}) - Streamer.get_topic_and_add_socket("user", user1) + Streamer.get_topic_and_add_socket("user", user1, user1_token) {:ok, _announce_activity} = CommonAPI.repeat(create_activity.id, user2) assert_receive {:render_with_user, _, "notification.json", notif} assert Streamer.filtered_by_user?(user1, notif) end - test "it send non-reblog notification for reblog-muted actors" do - user1 = insert(:user) + test "it send non-reblog notification for reblog-muted actors", %{ + user: user1, + token: user1_token + } do user2 = insert(:user) CommonAPI.follow(user1, user2) CommonAPI.hide_reblogs(user1, user2) {:ok, create_activity} = CommonAPI.post(user1, %{status: "I'm kawen"}) - Streamer.get_topic_and_add_socket("user", user1) + Streamer.get_topic_and_add_socket("user", user1, user1_token) {:ok, _favorite_activity} = CommonAPI.favorite(user2, create_activity.id) assert_receive {:render_with_user, _, "notification.json", notif} @@ -564,27 +657,28 @@ defmodule Pleroma.Web.StreamerTest do end end - test "it filters posts from muted threads" do - user = insert(:user) - user2 = insert(:user) - Streamer.get_topic_and_add_socket("user", user2) - {:ok, user2, user, _activity} = CommonAPI.follow(user2, user) - {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) - {:ok, _} = CommonAPI.add_mute(user2, activity) - assert_receive {:render_with_user, _, _, ^activity} - assert Streamer.filtered_by_user?(user2, activity) + describe "muted threads" do + test "it filters posts from muted threads" do + user = insert(:user) + %{user: user2, token: user2_token} = oauth_access(["read"]) + Streamer.get_topic_and_add_socket("user", user2, user2_token) + + {:ok, user2, user, _activity} = CommonAPI.follow(user2, user) + {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) + {:ok, _} = CommonAPI.add_mute(user2, activity) + + assert_receive {:render_with_user, _, _, ^activity} + assert Streamer.filtered_by_user?(user2, activity) + end end describe "direct streams" do - setup do - :ok - end + setup do: oauth_access(["read"]) - test "it sends conversation update to the 'direct' stream", %{} do - user = insert(:user) + test "it sends conversation update to the 'direct' stream", %{user: user, token: oauth_token} do another_user = insert(:user) - Streamer.get_topic_and_add_socket("direct", user) + Streamer.get_topic_and_add_socket("direct", user, oauth_token) {:ok, _create_activity} = CommonAPI.post(another_user, %{ @@ -602,11 +696,11 @@ defmodule Pleroma.Web.StreamerTest do assert last_status["pleroma"]["direct_conversation_id"] == participation.id end - test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted" do - user = insert(:user) + test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted", + %{user: user, token: oauth_token} do another_user = insert(:user) - Streamer.get_topic_and_add_socket("direct", user) + Streamer.get_topic_and_add_socket("direct", user, oauth_token) {:ok, create_activity} = CommonAPI.post(another_user, %{ @@ -629,10 +723,12 @@ defmodule Pleroma.Web.StreamerTest do refute_receive _ end - test "it sends conversation update to the 'direct' stream when a message is deleted" do - user = insert(:user) + test "it sends conversation update to the 'direct' stream when a message is deleted", %{ + user: user, + token: oauth_token + } do another_user = insert(:user) - Streamer.get_topic_and_add_socket("direct", user) + Streamer.get_topic_and_add_socket("direct", user, oauth_token) {:ok, create_activity} = CommonAPI.post(another_user, %{ diff --git a/test/web/twitter_api/password_controller_test.exs b/test/web/twitter_api/password_controller_test.exs @@ -37,7 +37,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do test "it returns HTTP 200", %{conn: conn} do user = insert(:user) {:ok, token} = PasswordResetToken.create_token(user) - {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{}) + {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{}) params = %{ "password" => "test", @@ -62,7 +62,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do user = insert(:user, password_reset_pending: true) {:ok, token} = PasswordResetToken.create_token(user) - {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{}) + {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{}) params = %{ "password" => "test", diff --git a/test/web/twitter_api/remote_follow_controller_test.exs b/test/web/twitter_api/remote_follow_controller_test.exs @@ -227,7 +227,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do } ) - {:ok, %{token: token}} = MFA.Token.create_token(user) + {:ok, %{token: token}} = MFA.Token.create(user) user2 = insert(:user) otp_token = TOTP.generate_token(otp_secret) @@ -256,7 +256,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do } ) - {:ok, %{token: token}} = MFA.Token.create_token(user) + {:ok, %{token: token}} = MFA.Token.create(user) user2 = insert(:user) otp_token = TOTP.generate_token(TOTP.generate_secret()) diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs @@ -21,170 +21,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do setup do: clear_config([:instance]) setup do: clear_config([:frontend_configurations, :pleroma_fe]) - describe "POST /api/pleroma/follow_import" do - setup do: oauth_access(["follow"]) - - test "it returns HTTP 200", %{conn: conn} do - user2 = insert(:user) - - response = - conn - |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"}) - |> json_response(:ok) - - assert response == "job started" - end - - test "it imports follow lists from file", %{user: user1, conn: conn} do - user2 = insert(:user) - - with_mocks([ - {File, [], - read!: fn "follow_list.txt" -> - "Account address,Show boosts\n#{user2.ap_id},true" - end} - ]) do - response = - conn - |> post("/api/pleroma/follow_import", %{"list" => %Plug.Upload{path: "follow_list.txt"}}) - |> json_response(:ok) - - assert response == "job started" - - assert ObanHelpers.member?( - %{ - "op" => "follow_import", - "follower_id" => user1.id, - "followed_identifiers" => [user2.ap_id] - }, - all_enqueued(worker: Pleroma.Workers.BackgroundWorker) - ) - end - end - - test "it imports new-style mastodon follow lists", %{conn: conn} do - user2 = insert(:user) - - response = - conn - |> post("/api/pleroma/follow_import", %{ - "list" => "Account address,Show boosts\n#{user2.ap_id},true" - }) - |> json_response(:ok) - - assert response == "job started" - end - - test "requires 'follow' or 'write:follows' permissions" do - token1 = insert(:oauth_token, scopes: ["read", "write"]) - token2 = insert(:oauth_token, scopes: ["follow"]) - token3 = insert(:oauth_token, scopes: ["something"]) - another_user = insert(:user) - - for token <- [token1, token2, token3] do - conn = - build_conn() - |> put_req_header("authorization", "Bearer #{token.token}") - |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"}) - - if token == token3 do - assert %{"error" => "Insufficient permissions: follow | write:follows."} == - json_response(conn, 403) - else - assert json_response(conn, 200) - end - end - end - - test "it imports follows with different nickname variations", %{conn: conn} do - [user2, user3, user4, user5, user6] = insert_list(5, :user) - - identifiers = - [ - user2.ap_id, - user3.nickname, - " ", - "@" <> user4.nickname, - user5.nickname <> "@localhost", - "@" <> user6.nickname <> "@localhost" - ] - |> Enum.join("\n") - - response = - conn - |> post("/api/pleroma/follow_import", %{"list" => identifiers}) - |> json_response(:ok) - - assert response == "job started" - assert [{:ok, job_result}] = ObanHelpers.perform_all() - assert job_result == [user2, user3, user4, user5, user6] - end - end - - describe "POST /api/pleroma/blocks_import" do - # Note: "follow" or "write:blocks" permission is required - setup do: oauth_access(["write:blocks"]) - - test "it returns HTTP 200", %{conn: conn} do - user2 = insert(:user) - - response = - conn - |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"}) - |> json_response(:ok) - - assert response == "job started" - end - - test "it imports blocks users from file", %{user: user1, conn: conn} do - user2 = insert(:user) - user3 = insert(:user) - - with_mocks([ - {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} - ]) do - response = - conn - |> post("/api/pleroma/blocks_import", %{"list" => %Plug.Upload{path: "blocks_list.txt"}}) - |> json_response(:ok) - - assert response == "job started" - - assert ObanHelpers.member?( - %{ - "op" => "blocks_import", - "blocker_id" => user1.id, - "blocked_identifiers" => [user2.ap_id, user3.ap_id] - }, - all_enqueued(worker: Pleroma.Workers.BackgroundWorker) - ) - end - end - - test "it imports blocks with different nickname variations", %{conn: conn} do - [user2, user3, user4, user5, user6] = insert_list(5, :user) - - identifiers = - [ - user2.ap_id, - user3.nickname, - "@" <> user4.nickname, - user5.nickname <> "@localhost", - "@" <> user6.nickname <> "@localhost" - ] - |> Enum.join(" ") - - response = - conn - |> post("/api/pleroma/blocks_import", %{"list" => identifiers}) - |> json_response(:ok) - - assert response == "job started" - assert [{:ok, job_result}] = ObanHelpers.perform_all() - assert job_result == [user2, user3, user4, user5, user6] - end - end - describe "PUT /api/pleroma/notification_settings" do setup do: oauth_access(["write:accounts"]) @@ -594,7 +430,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do user = User.get_by_id(user.id) assert user.deactivated == true assert user.name == nil - assert user.bio == nil + assert user.bio == "" assert user.password_hash == nil end end diff --git a/test/workers/cron/clear_oauth_token_worker_test.exs b/test/workers/cron/clear_oauth_token_worker_test.exs @@ -1,22 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Workers.Cron.ClearOauthTokenWorkerTest do - use Pleroma.DataCase - - import Pleroma.Factory - alias Pleroma.Workers.Cron.ClearOauthTokenWorker - - setup do: clear_config([:oauth2, :clean_expired_tokens]) - - test "deletes expired tokens" do - insert(:oauth_token, - valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), -60 * 10) - ) - - Pleroma.Config.put([:oauth2, :clean_expired_tokens], true) - ClearOauthTokenWorker.perform(%Oban.Job{}) - assert Pleroma.Repo.all(Pleroma.Web.OAuth.Token) == [] - end -end diff --git a/test/workers/cron/purge_expired_activities_worker_test.exs b/test/workers/cron/purge_expired_activities_worker_test.exs @@ -1,84 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do - use Pleroma.DataCase - - alias Pleroma.ActivityExpiration - alias Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker - - import Pleroma.Factory - import ExUnit.CaptureLog - - setup do - clear_config([ActivityExpiration, :enabled]) - end - - test "deletes an expiration activity" do - Pleroma.Config.put([ActivityExpiration, :enabled], true) - activity = insert(:note_activity) - - naive_datetime = - NaiveDateTime.add( - NaiveDateTime.utc_now(), - -:timer.minutes(2), - :millisecond - ) - - expiration = - insert( - :expiration_in_the_past, - %{activity_id: activity.id, scheduled_at: naive_datetime} - ) - - Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{}) - - refute Pleroma.Repo.get(Pleroma.Activity, activity.id) - refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id) - end - - test "works with ActivityExpirationPolicy" do - Pleroma.Config.put([ActivityExpiration, :enabled], true) - - clear_config([:mrf, :policies], Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy) - - user = insert(:user) - - days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365) - - {:ok, %{id: id} = activity} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"}) - - past_date = - NaiveDateTime.utc_now() |> Timex.shift(days: -days) |> NaiveDateTime.truncate(:second) - - activity - |> Repo.preload(:expiration) - |> Map.get(:expiration) - |> Ecto.Changeset.change(%{scheduled_at: past_date}) - |> Repo.update!() - - Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{}) - - assert [%{data: %{"type" => "Delete", "deleted_activity_id" => ^id}}] = - Pleroma.Repo.all(Pleroma.Activity) - end - - describe "delete_activity/1" do - test "adds log message if activity isn't find" do - assert capture_log([level: :error], fn -> - PurgeExpiredActivitiesWorker.delete_activity(%ActivityExpiration{ - activity_id: "test-activity" - }) - end) =~ "Couldn't delete expired activity: not found activity" - end - - test "adds log message if actor isn't find" do - assert capture_log([level: :error], fn -> - PurgeExpiredActivitiesWorker.delete_activity(%ActivityExpiration{ - activity_id: "test-activity" - }) - end) =~ "Couldn't delete expired activity: not found activity" - end - end -end diff --git a/test/workers/purge_expired_activity_test.exs b/test/workers/purge_expired_activity_test.exs @@ -0,0 +1,59 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.PurgeExpiredActivityTest do + use Pleroma.DataCase, async: true + use Oban.Testing, repo: Pleroma.Repo + + import Pleroma.Factory + + alias Pleroma.Workers.PurgeExpiredActivity + + test "enqueue job" do + activity = insert(:note_activity) + + assert {:ok, _} = + PurgeExpiredActivity.enqueue(%{ + activity_id: activity.id, + expires_at: DateTime.add(DateTime.utc_now(), 3601) + }) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity.id} + ) + + assert {:ok, _} = + perform_job(Pleroma.Workers.PurgeExpiredActivity, %{activity_id: activity.id}) + + assert %Oban.Job{} = Pleroma.Workers.PurgeExpiredActivity.get_expiration(activity.id) + end + + test "error if user was not found" do + activity = insert(:note_activity) + + assert {:ok, _} = + PurgeExpiredActivity.enqueue(%{ + activity_id: activity.id, + expires_at: DateTime.add(DateTime.utc_now(), 3601) + }) + + user = Pleroma.User.get_by_ap_id(activity.actor) + Pleroma.Repo.delete(user) + + assert {:error, :user_not_found} = + perform_job(Pleroma.Workers.PurgeExpiredActivity, %{activity_id: activity.id}) + end + + test "error if actiivity was not found" do + assert {:ok, _} = + PurgeExpiredActivity.enqueue(%{ + activity_id: "some_id", + expires_at: DateTime.add(DateTime.utc_now(), 3601) + }) + + assert {:error, :activity_not_found} = + perform_job(Pleroma.Workers.PurgeExpiredActivity, %{activity_id: "some_if"}) + end +end diff --git a/test/workers/purge_expired_token_test.exs b/test/workers/purge_expired_token_test.exs @@ -0,0 +1,51 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.PurgeExpiredTokenTest do + use Pleroma.DataCase, async: true + use Oban.Testing, repo: Pleroma.Repo + + import Pleroma.Factory + + setup do: clear_config([:oauth2, :clean_expired_tokens], true) + + test "purges expired oauth token" do + user = insert(:user) + app = insert(:oauth_app) + + {:ok, %{id: id}} = Pleroma.Web.OAuth.Token.create(app, user) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredToken, + args: %{token_id: id, mod: Pleroma.Web.OAuth.Token} + ) + + assert {:ok, %{id: ^id}} = + perform_job(Pleroma.Workers.PurgeExpiredToken, %{ + token_id: id, + mod: Pleroma.Web.OAuth.Token + }) + + assert Repo.aggregate(Pleroma.Web.OAuth.Token, :count, :id) == 0 + end + + test "purges expired mfa token" do + authorization = insert(:oauth_authorization) + + {:ok, %{id: id}} = Pleroma.MFA.Token.create(authorization.user, authorization) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredToken, + args: %{token_id: id, mod: Pleroma.MFA.Token} + ) + + assert {:ok, %{id: ^id}} = + perform_job(Pleroma.Workers.PurgeExpiredToken, %{ + token_id: id, + mod: Pleroma.MFA.Token + }) + + assert Repo.aggregate(Pleroma.MFA.Token, :count, :id) == 0 + end +end