123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 |
- (*
- * _ _ ____ _
- * _| || |_/ ___| ___ _ __ _ __ ___ | |
- * |_ .. _\___ \ / _ \ '_ \| '_ \ / _ \| |
- * |_ _|___) | __/ |_) | |_) | (_) |_|
- * |_||_| |____/ \___| .__/| .__/ \___/(_)
- * |_| |_|
- *
- * Personal Social Web.
- *
- * t_as2.ml
- *
- * Copyright (C) The #Seppo contributors. All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *)
- open Seppo_lib
- open Alcotest
- module A = Assrt
- let set_up () =
- Mirage_crypto_rng_lwt.initialize (module Mirage_crypto_rng.Fortuna);
- Unix.chdir "../../../test/"
- let tc_follower_state () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_follower_state");
- Ap.Followers.State.(Pending |> to_string) |>
- check string __LOC__ "pending"
- let tc_inbox_follow () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_inbox_follow");
- let a = "data/follow.mastodon.json"
- |> File.in_channel Ezjsonm.from_channel
- |> As2_vocab.Activitypub.Decode.follow
- |> Result.get_ok in
- a.id |> A.equals_uri __LOC__ (Uri.of_string "https://alpaka.social/afe4ac8a-aaeb-41f5-a348-e5d133bdb931");
- a.actor |> A.equals_uri __LOC__ (Uri.of_string "https://alpaka.social/users/traunstein");
- a.object_ |> A.equals_uri __LOC__ (Uri.of_string "https://dev.seppo.social/2023-06-12/activitypub/profile.json");
- match a.state with
- | None -> ()
- | _ -> "-" |> A.equals_string __LOC__ ""
- let tc_inbox_unfollow () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_inbox_unfollow");
- let o = "data/undo-follow.mastodon.json"
- |> File.in_channel Ezjsonm.from_channel
- |> As2_vocab.Activitypub.Decode.(undo follow)
- |> Result.get_ok in
- o.id |> Uri.to_string |> A.equals_string __LOC__ "https://alpaka.social/users/traunstein#follows/5219/undo";
- o.actor |> Uri.to_string |> A.equals_string __LOC__ "https://alpaka.social/users/traunstein";
- o.obj.id |> Uri.to_string |> A.equals_string __LOC__ "https://alpaka.social/a5fc3ab5-92f3-4641-a33e-96418e9bec78";
- o.obj.object_ |> Uri.to_string |> A.equals_string __LOC__ "https://dev.seppo.social/2023-06-12/activitypub/profile.json";
- assert (o.actor |> Uri.equal o.obj.actor);
- (*
- a.object_ |> A.equals_uri __LOC__ (Uri.of_string "https://dev.seppo.social/2023-06-12/activitypub/profile.json");
- match a.state with
- | None -> ()
- | _ -> "-" |> A.equals_string __LOC__ ""
- *)
- assert true
- let tc_followers_page_json_raw () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_followers_page_json_raw");
- let fs = [
- "1/" |> Uri.of_string;
- "2/" |> Uri.of_string;
- "3/" |> Uri.of_string;
- "4/" |> Uri.of_string;
- "5/" |> Uri.of_string;
- ] in
- let base' = "https://example.com/u/" |> Uri.of_string in
- let base = "https://example.com/ap/followers/2.jsa" |> Uri.of_string in
- let p : Uri.t As2_vocab.Types.collection_page = {
- id = base;
- current = Some base;
- first = None;
- is_ordered = true;
- items = fs;
- last = Some (Http.reso ~base (Uri.of_string "0.jsa"));
- next = Some (Http.reso ~base (Uri.of_string "1.jsa"));
- part_of = Some (Http.reso ~base (Uri.of_string "index.jsa"));
- prev = Some (Http.reso ~base (Uri.of_string "3.jsa"));
- total_items= None;
- } in
- p |> As2_vocab.Encode.(collection_page ~base (uri ~base:base'))
- |> Ezjsonm.value_to_string ~minify:false
- |> A.equals_string __LOC__ {|{
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- {
- "schema": "http://schema.org#",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value",
- "@language": "und"
- }
- ],
- "type": "OrderedCollectionPage",
- "id": "https://example.com/ap/followers/2.jsa",
- "current": "https://example.com/ap/followers/2.jsa",
- "last": "https://example.com/ap/followers/0.jsa",
- "next": "https://example.com/ap/followers/1.jsa",
- "partOf": "https://example.com/ap/followers/index.jsa",
- "prev": "https://example.com/ap/followers/3.jsa",
- "orderedItems": [
- "https://example.com/u/1/",
- "https://example.com/u/2/",
- "https://example.com/u/3/",
- "https://example.com/u/4/",
- "https://example.com/u/5/"
- ]
- }|}
- let tc_followers_page_json () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_followers_page_json");
- let foo = "https://example.com/foo/usr/" |> Uri.of_string in
- let base = "https://example.com/" |> Uri.of_string in
- let path = Ap.apub ^ "followers/" in
- let base = Http.reso ~base (Uri.make ~path ()) in
- [ "1/"; "2/"; "3/"; "4/"; "5/" ]
- |> List.rev
- |> List.fold_left (fun init path -> (Uri.make ~path () |> Http.reso ~base:foo) :: init) []
- |> Ap.Followers.Json.to_page_json ~base path ~is_last:false 2
- |> Ezjsonm.value_to_string ~minify:false
- |> A.equals_string __LOC__ {|{
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- {
- "schema": "http://schema.org#",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value",
- "@language": "und"
- }
- ],
- "type": "OrderedCollectionPage",
- "id": "https://example.com/activitypub/followers/2.jsa",
- "current": "https://example.com/activitypub/followers/2.jsa",
- "last": "https://example.com/activitypub/followers/0.jsa",
- "next": "https://example.com/activitypub/followers/1.jsa",
- "partOf": "https://example.com/activitypub/followers/index.jsa",
- "prev": "https://example.com/activitypub/followers/3.jsa",
- "orderedItems": [
- "https://example.com/foo/usr/1/",
- "https://example.com/foo/usr/2/",
- "https://example.com/foo/usr/3/",
- "https://example.com/foo/usr/4/",
- "https://example.com/foo/usr/5/"
- ]
- }|}
- let tc_followers_json () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_followers_json");
- let foo = "https://example.com/foo/usr/" |> Uri.of_string in
- let lst = [ "1/"; "2/"; "3/"; "4/"; "5/" ]
- |> List.rev
- |> List.fold_left (fun init path -> (Uri.make ~path () |> Http.reso ~base:foo) :: init) []
- in
- let base = "https://example.com/" |> Uri.of_string in
- let path = Ap.apub ^ "followers/" in
- let base = Http.reso ~base (Uri.make ~path ()) in
- let _ = File.mkdir_p File.pDir path in
- (* let oc = stdout in *)
- "/dev/null" |> File.out_channel_append (fun oc ->
- Ap.Followers.Json.(List.fold_left
- (fold2pages 3 (flush_page_json ~base ~oc path))
- (0,0,[],0)
- lst
- |> flush_page_json ~base ~is_last:true ~oc path);
- (* check existence of index.jsa *)
- (* check existence of 0.jsa *)
- (* check existence of 1.jsa *)
- "" |> A.equals_string __LOC__ ""
- )
- let tc_followers_cdb_json () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_followers_cdb_json");
- "/dev/null" |> File.out_channel_append (fun oc ->
- let base = "https://example.com/" |> Uri.of_string in
- let path = Ap.apub ^ "follower2/" in
- let base = Http.reso ~base (Uri.make ~path ()) in
- let path = "tmp/" ^ path in
- let _ = File.mkdir_p File.pDir path in
- let _ = Ap.Followers.Json.coll_of_cdb ~base ~oc ~pagesize:3 path (Mapcdb.Cdb "data/followers.cdb") in
- "" |> A.equals_string __LOC__ ""
- )
- module Note = struct
- let tc_of_rfc4287 () =
- let open Rfc4287 in
- let e = {Entry.empty with
- id = "" |> Uri.of_string;
- lang = Rfc4646 "nl";
- title = "Title";
- published = Rfc3339.T "2023-10-24T11:12:13+02:00";
- updated = Rfc3339.T "2023-10-24T11:12:13+02:00";
- links = [Link.make ("https://Seppo.Social/demo" |> Uri.of_string) ];
- content = "string";
- } in
- e.title |> check string __LOC__ "Title";
- let n = e |> Ap.Note.of_rfc4287 in
- let _,su = n.summary_map |> List.hd in
- su |> check string __LOC__ "Title";
- n.url |> List.hd |> Uri.to_string |> check string __LOC__ "https://seppo.social/demo"
- let tc_create_note_json () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_create_note_json");
- "data/create.note.mastodon2.json" |> File.in_channel (fun ic ->
- let c : As2_vocab.Types.note As2_vocab.Types.create = Ezjsonm.from_channel ic
- |> As2_vocab.Decode.(create note)
- |> Result.get_ok in
- assert (not c.direct_message);
- let n = c.obj in
- n.id |> Uri.to_string |> A.equals_string __LOC__ "https://bewegung.social/users/mro/statuses/111561416759041219";
- n.attributed_to |> Uri.to_string |> A.equals_string __LOC__ "https://bewegung.social/users/mro";
- n.published |> Option.get |> Ptime.to_rfc3339 |> A.equals_string __LOC__ "2023-12-11T10:55:25-00:00";
- n.in_reply_to |> List.length |> A.equals_int __LOC__ 0;
- assert (n.summary_map |> List.length = 0);
- let _,co = n.content_map |> List.hd in
- co |> A.equals_string __LOC__ {|<p>Good morning 😀 <a href="https://bewegung.social/tags/Social" class="mention hashtag" rel="tag">#<span>Social</span></a> <a href="https://bewegung.social/tags/Web" class="mention hashtag" rel="tag">#<span>Web</span></a>! <span class="h-card" translate="no"><a href="https://seppo.social/demo/" class="u-url mention">@<span>demo</span></a></span></p>|};
- n.tags |> List.length |> A.equals_int __LOC__ 3;
- (match n.tags with
- | [
- {ty=`Mention;name=n0;href=h0};
- {ty=`Hashtag;name=n1;href=h1};
- {ty=`Hashtag;name=n2;href=h2};
- ] ->
- n0 |> A.equals_string __LOC__ "@demo@seppo.social";
- h0 |> Uri.to_string |> A.equals_string __LOC__ "https://seppo.social/demo/activitypub/profile.jlda";
- n1 |> A.equals_string __LOC__ "#social";
- h1 |> Uri.to_string |> A.equals_string __LOC__ "https://bewegung.social/tags/social";
- n2 |> A.equals_string __LOC__ "#web";
- h2 |> Uri.to_string |> A.equals_string __LOC__ "https://bewegung.social/tags/web";
- ()
- | _ -> failwith "aua"
- (**) );
- assert true
- )
- let tc_diluviate () =
- let n =
- {Ap.Note.empty with
- id = "https://example.com/1" |> Uri.of_string;
- sensitive = true;
- content_map= ["de","Inhalt"];
- summary_map= ["de","⚠️ Summary"];
- url = ["https://Seppo.Social/demo" |> Uri.of_string];
- } in
- let base = Uri.empty in
- let minify = false in
- n
- |> Ap.Note.diluviate
- |> As2_vocab.Encode.note ~base |> Ezjsonm.value_to_string ~minify
- |> Assrt.equals_string
- __LOC__ {|{
- "type": "Note",
- "id": "https://example.com/1",
- "attributedTo": "",
- "mediaType": "text/html; charset=utf8",
- "contentMap": {
- "de": "<a href='https://seppo.social/demo'>https://seppo.social/demo</a><br/>\n<br/>\nInhalt"
- },
- "sensitive": true,
- "summaryMap": {
- "de": "⚠️ Summary"
- },
- "url": "https://example.com/1"
- }|};
- assert true
- let tc_note_to_plain () =
- (*
- test/data/ap/inbox/create/note/note-OZcAekXDY1A.json
- *)
- ()
- end
- let tc_create_follow_json () =
- let to_actor = "http://example.com/to/actor" |> Uri.of_string
- and from_actor = "http://example.com/from/actor" |> Uri.of_string
- and to_inbox = "http://example.com/to/inbox" |> Uri.of_string
- and base = "http://example.com/from/" |> Uri.of_string
- and tnow = Ptime.of_date_time ((2024,1,2), ((3,4,5),60*60)) |> Option.value ~default:Ptime.max
- and minify = false in
- let _fo = to_actor |> Ap.Following.make ~tnow ~me:from_actor ~inbox:to_inbox in
- _fo
- |> As2_vocab.Encode.follow ~base
- |> Ezjsonm.value_to_string ~minify |>
- Assrt.equals_string
- __LOC__ {|{
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- {
- "schema": "http://schema.org#",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value",
- "@language": "und"
- }
- ],
- "type": "Follow",
- "id": "http://example.com/from/actor#subscribe",
- "actor": "http://example.com/from/actor",
- "endTime": "2024-04-03T02:04:05Z",
- "object": "http://example.com/to/actor"
- }|}
- let tc_reject_json () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "test_reject_json");
- let reject me id =
- `O [("@context", `String "https://www.w3.org/ns/activitystreams");
- ("type", `String "Reject");
- ("actor", `String (me |> Uri.to_string));
- ("object", `String (id |> Uri.to_string))]
- in
- let me = "https://example.com/alice" |> Uri.of_string in
- let id = match "data/create.note.mastodon2.json" |> File.in_channel Ezjsonm.from_channel with
- | `O (_ :: ("id", `String id) :: _) -> id |> Uri.of_string
- | _ -> Uri.empty in
- id |> Uri.to_string |> A.equals_string __LOC__ {|https://bewegung.social/users/mro/statuses/111561416759041219/activity|};
- id
- |> reject me
- |> Ezjsonm.value_to_string
- |> A.equals_string __LOC__ {|{"@context":"https://www.w3.org/ns/activitystreams","type":"Reject","actor":"https://example.com/alice","object":"https://bewegung.social/users/mro/statuses/111561416759041219/activity"}|};
- assert true
- let tc_subscribed () =
- Logr.info (fun m -> m "%s" __LOC__);
- for i = 0 to 10 do
- try i |> Printf.sprintf "/tmp/%d.xml" |> Unix.unlink
- with | Unix.Unix_error(Unix.ENOENT, "unlink", _) -> ()
- done ;
- let cdb = Mapcdb.Cdb "data/2024-04-30-131146-subscribed.cdb" in
- cdb
- |> Mapcdb.fold_left (fun c _ -> 1 + c) 0
- |> A.equals_int __LOC__ 52;
- let r = Ap.Followers.Atom.rule in
- r.target |> A.equals_string __LOC__ "activitypub/subscribers/index.xml";
- (match Ap.Followers.Atom.of_cdb
- ~cdb
- ~base:("https://example.com/" |> Uri.of_string)
- ~title:"My Title"
- ~xsl:(Rfc4287.xsl "my.xsl" "./tmp/noop")
- ~rel:(Some Rfc4287.Link.subscribers)
- ~page_size:5
- "./tmp/" with
- | Error _ -> failwith __LOC__
- | Ok s -> s)
- |> A.equals_string __LOC__ "./tmp/10.xml";
- "./tmp/0.xml" |> File.to_string |> A.equals_string __LOC__ {|<?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="../../themes/current/my.xsl"?>
- <feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://example.com/">
- <title>My Title</title>
- <id>0.xml</id>
- <link rel="self" href="0.xml" title="1"/>
- <link rel="first" href="." title="last"/>
- <link rel="last" href="0.xml" title="1"/>
- <link rel="previous" href="1.xml" title="2"/>
- <link rel="subscribers" href="https://social.wohlfarth.name/users/alain" title=""/>
- <link rel="subscribers" href="https://hci.social/users/sigchi" title=""/>
- <link rel="subscribers" href="https://fosstodon.org/users/nlnetlabs" title=""/>
- <link rel="subscribers" href="https://mastodon.xyz/users/NGIZero" title=""/>
- <link rel="subscribers" href="https://w3c.social/users/w3c" title=""/>
- </feed>|};
- "./tmp/10.xml" |> File.to_string |> A.equals_string __LOC__ {|<?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="../../themes/current/my.xsl"?>
- <feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://example.com/">
- <title>My Title</title>
- <id>10.xml</id>
- <link rel="self" href="10.xml" title="11"/>
- <link rel="first" href="." title="last"/>
- <link rel="last" href="0.xml" title="1"/>
- <link rel="previous" href="11.xml" title="12"/>
- <link rel="next" href="9.xml" title="10"/>
- <link rel="subscribers" href="https://mas.to/users/leostera" title=""/>
- <link rel="subscribers" href="https://social.network.europa.eu/users/EU_Commission" title="European Commission" rfc7565="acct:EU_Commission@social.network.europa.eu"/>
- </feed>|};
- "?" |> A.equals_string __LOC__ "?"
- let tc_to_rfc4287_0 () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "to_rfc4287_0");
- let now = ((2024,3,19), ((1,2,3),60*60)) |> Ptime.of_date_time
- and tz = Timedesc.Time_zone.utc in
- let n = {Ap.Note.empty with
- id = "https://example.com/o/42" |> Uri.of_string;
- attributed_to = "https://example.com/a/23" |> Uri.of_string;
- content_map = ["en","Some Content"];
- published = now;
- summary_map = ["en","No content warning"];
- } in
- let now = now |> Option.value ~default:Ptime.epoch in
- let a = n |> Ap.Note.to_rfc4287 ~tz ~now in
- a.id |> Uri.to_string |> Assrt.equals_string __LOC__ "https://example.com/o/42";
- a.author.uri |> Option.value ~default:Uri.empty |> Uri.to_string |> Assrt.equals_string __LOC__ "https://example.com/a/23";
- let Rfc3339.T t = a.published in
- t |> Assrt.equals_string __LOC__ "2024-03-19T00:02:03Z";
- a.title |> Assrt.equals_string __LOC__ "No content warning";
- a.content |> Assrt.equals_string __LOC__ "Some Content";
- ()
- let tc_to_rfc4287_loaded () =
- Logr.info (fun m -> m "%s.%s" "Ap_test" "to_rfc4287_loaded");
- let load_note fn =
- let fn = "data/ap/inbox/create/note/" ^ fn in
- fn
- |> File.in_channel
- (fun ic ->
- match ic |> Ezjsonm.from_channel |> As2_vocab.Activitypub.Decode.obj with
- | Error _ -> failwith "failed to load note"
- | Ok o -> match o with
- | `Create { obj = `Note obj; _ } -> obj
- | _ -> failwith "strange type")
- in
- let now = ((2024,3,19), ((1,2,3),60*60)) |> Ptime.of_date_time |> Option.get
- and tz = Timedesc.Time_zone.utc
- and base = "https://example.com/fe/" |> Uri.of_string
- and attr = [ ((Xmlm.ns_xmlns,"xmlns"),Xml.ns_a);
- ((Xmlm.ns_xmlns,"thr") ,Xml.ns_thr);
- ((Xmlm.ns_xmlns,"as") ,Xml.ns_as);
- ((Xmlm.ns_xmlns,"wf") ,Xml.ns_rfc7033); ] in
- let apu = load_note "note-Hjcb9bqwCgk.json" in
- let ato = apu |> Ap.Note.to_rfc4287 ~tz ~now in
- ato.author.name |> Assrt.equals_string __LOC__ "https://mastodon.social/users/nicholas_saunders";
- ato.author.uri |> Option.value ~default:Uri.empty |> Uri.to_string |> Assrt.equals_string __LOC__ "https://mastodon.social/users/nicholas_saunders";
- ato.content |> Assrt.equals_string __LOC__ {|@wschenk@floss.social @geoglyphentropy@mstdn.social @nus@mstdn.social @DavidKafri@tooot.im @thetechtutor@me.dm After the Goat refused to explain what military action in response to the #alaqsaflood[1] would've been moral he lost all priveleges with me, although he eventually admitted that nothing would meet his standards. Eventually he blocked me, although he seems to have somehow replied to me.
- I'm inferring that this has something to with the Goat, but have no idea. Guess I'll never know what it was about.
- [1]: https://mastodon.social/tags/alaqsaflood|};
- let buf = 1024 |> Buffer.create in
- buf |> Xml.to_buf (ato |> Rfc4287.Entry.to_atom ~attr ~base);
- buf |> Buffer.to_bytes |> Bytes.to_string |> Assrt.equals_string __LOC__ {|<?xml version="1.0"?>
- <entry xml:lang="en" xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:as="https://www.w3.org/ns/activitystreams" xmlns:wf="urn:ietf:rfc:7033">
- <id>https://mastodon.social/users/nicholas_saunders/statuses/112615088973179734</id>
- <title type="text"></title>
- <updated>2024-06-14T12:58:07Z</updated>
- <published>2024-06-14T12:58:07Z</published>
- <as:sensitive>false</as:sensitive>
- <author>
- <name>https://mastodon.social/users/nicholas_saunders</name>
- <wf:uri></wf:uri>
- <uri>https://mastodon.social/users/nicholas_saunders</uri></author>
- <link rel="self" href="https://mastodon.social/users/nicholas_saunders/statuses/112615088973179734"/>
- <thr:in-reply-to ref="https://floss.social/users/wschenk/statuses/112615060106830322"/>
- <content type="text">@wschenk@floss.social @geoglyphentropy@mstdn.social @nus@mstdn.social @DavidKafri@tooot.im @thetechtutor@me.dm After the Goat refused to explain what military action in response to the #alaqsaflood[1] would've been moral he lost all priveleges with me, although he eventually admitted that nothing would meet his standards. Eventually he blocked me, although he seems to have somehow replied to me.
- I'm inferring that this has something to with the Goat, but have no idea. Guess I'll never know what it was about.
- [1]: https://mastodon.social/tags/alaqsaflood</content>
- </entry>|};
- ();
- let apu : As2_vocab.Types.note = load_note "note-OiqQGte9TSY.json" in
- (match apu.in_reply_to with
- | [ u ] -> u |> Uri.to_string |> Assrt.equals_string __LOC__ {|https://infosec.exchange/users/womble/statuses/112948594753912420|}
- | _ -> failwith __LOC__);
- let ato : Rfc4287.Entry.t = apu |> Ap.Note.to_rfc4287 ~tz ~now in
- apu.in_reply_to |> List.length |> Assrt.equals_int __LOC__ 1;
- ato.in_reply_to |> List.length |> Assrt.equals_int __LOC__ (apu.in_reply_to |> List.length);
- buf |> Buffer.clear;
- buf |> Xml.to_buf (ato |> Rfc4287.Entry.to_atom ~attr ~base);
- buf |> Buffer.to_bytes |> Bytes.to_string |> Assrt.equals_string __LOC__ {|<?xml version="1.0"?>
- <entry xml:lang="und" xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:as="https://www.w3.org/ns/activitystreams" xmlns:wf="urn:ietf:rfc:7033">
- <id>https://benjojo.co.uk/u/benjojo/h/89L5knBH4TGG4qY4VT</id>
- <title type="text"></title>
- <updated>2024-08-12T10:40:45Z</updated>
- <published>2024-08-12T10:40:45Z</published>
- <as:sensitive>false</as:sensitive>
- <author>
- <name>benjojo</name>
- <wf:uri>acct:benjojo@benjojo.co.uk</wf:uri>
- <uri>https://benjojo@benjojo.co.uk/u/benjojo</uri></author>
- <link rel="self" href="https://benjojo.co.uk/u/benjojo/h/89L5knBH4TGG4qY4VT"/>
- <thr:in-reply-to ref="https://infosec.exchange/users/womble/statuses/112948594753912420"/>
- <content type="text">@womble@infosec.exchange It's automatically enabled on most modern android devices and as far as I understand iPhones too. I would assume either the phone that is sending the messages just enabled it seemlessly with w/e API they are using to dispatch messages, or that they are assuming (probably correctly) that whatever carrier side spam filtering exists on the SMS end does not get applied on the RCS end</content>
- </entry>|};
- ()
- let tc_decode_create_notes () =
- Logr.info (fun m -> m "%s" __LOC__);
- let dir = "data/ap/inbox/create/note/" in
- let l : As2_vocab.Types.note list =
- dir |> File.fold_dir
- (fun init f ->
- let f = dir ^ f in
- try
- let j = f |> File.in_channel Ezjsonm.from_channel in
- (match j |> As2_vocab.Activitypub.Decode.obj with
- | Ok `Update { obj = `Note obj; _ }
- | Ok `Create { obj = `Note obj; _ } -> obj :: init
- | _ ->
- Logr.debug (fun m -> m "%s %s no!" "decode_create_notes" f);
- init),true
- with
- | e ->
- Logr.debug (fun m -> m "%s %s ouch! %s" "decode_create_notes" f (Printexc.to_string e));
- init,true)
- [] in
- l |> List.length |> Assrt.equals_int __LOC__ 204;
- let now = ((2024,3,19), ((1,2,3),60*60)) |> Ptime.of_date_time |> Option.value ~default:Ptime.epoch in
- let tz = Timedesc.Time_zone.make "Europe/Amsterdam" |> Option.value ~default:Timedesc.Time_zone.utc in
- let l = l |> List.map (Ap.Note.to_rfc4287 ~tz ~now) in
- l |> List.length |> Assrt.equals_int __LOC__ 204;
- let l = l |> List.sort Rfc4287.Entry.compare in
- let l = l |> List.filteri (fun i _ -> i < 2) in
- let x = l |> Rfc4287.Feed.to_atom
- ~base:(Uri.of_string "http://example.com/")
- ~self:(Uri.of_string "seppo.cgi/p-37/")
- ~prev:None
- ~next:None
- ~first:(Uri.of_string "seppo.cgi/p-37/")
- ~last:(Uri.of_string "seppo.cgi/p-0/")
- ~title:"ti"
- ~updated:(Rfc3339.T "2024-06-19 16:15:14+02:00")
- ~lang:(Rfc4287.Rfc4646 "de")
- ~author:{Rfc4287.Person.empty with
- name = "Alice";
- uri = Some ("alice@example.com" |> Uri.of_string)} in
- let fn = "./tmp/as2_vocab_text.dat" in
- (try fn |> Unix.unlink with _ -> ());
- fn |> File.out_channel_replace (x |> Xml.to_chan ~xsl:(Rfc4287.xsl "posts.xsl" fn));
- (match fn |> File.cat with
- | Error _ -> failwith __LOC__
- | Ok s -> s)
- |> Assrt.equals_string __LOC__ {|<?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="../../themes/current/posts.xsl"?>
- <feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:wf="urn:ietf:rfc:7033" xmlns:as="https://www.w3.org/ns/activitystreams" xml:lang="de" xml:base="http://example.com/">
- <id>http://example.com/seppo.cgi/p-37/</id>
- <title type="text">ti</title>
- <updated>2024-06-19 16:15:14+02:00</updated>
- <generator uri="Seppo.Social">Seppo - Personal Social Web</generator>
- <link rel="self" href="seppo.cgi/p-37/" title="38"/>
- <link rel="first" href="seppo.cgi/p-37/" title="last"/>
- <link rel="last" href="seppo.cgi/p-0/" title="1"/>
- <entry xml:lang="en">
- <id>https://mastodon.social/users/nicholas_saunders/statuses/112608234771751001</id>
- <title type="text"></title>
- <updated>2024-06-13T09:55:01+02:00</updated>
- <published>2024-06-13T09:55:01+02:00</published>
- <as:sensitive>false</as:sensitive>
- <author>
- <name>https://mastodon.social/users/nicholas_saunders</name>
- <wf:uri></wf:uri>
- <uri>https://mastodon.social/users/nicholas_saunders</uri></author>
- <link rel="self" href="https://mastodon.social/users/nicholas_saunders/statuses/112608234771751001"/>
- <thr:in-reply-to ref="https://infosec.exchange/users/SpaceLifeForm/statuses/112608204971110992"/>
- <content type="text">@SpaceLifeForm@infosec.exchange @RickiTarr@beige.party I'll be here all day @SpaceLifeForm@infosec.exchange :)
- (not really.)</content>
- </entry>
- <entry xml:lang="en">
- <id>https://mastodon.social/users/nicholas_saunders/statuses/112606941257663038</id>
- <title type="text"></title>
- <updated>2024-06-13T04:26:03+02:00</updated>
- <published>2024-06-13T04:26:03+02:00</published>
- <as:sensitive>false</as:sensitive>
- <author>
- <name>https://mastodon.social/users/nicholas_saunders</name>
- <wf:uri></wf:uri>
- <uri>https://mastodon.social/users/nicholas_saunders</uri></author>
- <link rel="self" href="https://mastodon.social/users/nicholas_saunders/statuses/112606941257663038"/>
- <thr:in-reply-to ref="https://mastodon.social/users/thejapantimes/statuses/112606642206596379"/>
- <content type="text">@thejapantimes@mastodon.social so then #hamas[1] didn't accept the offer, but rather seeks different terms.
- [1]: https://mastodon.social/tags/hamas</content>
- </entry>
- </feed>|}
- let () =
- run
- "seppo_suite" [
- __FILE__ , [
- "set_up", `Quick, set_up;
- "tc_follower_state", `Quick, tc_follower_state;
- "tc_inbox_follow", `Quick, tc_inbox_follow;
- "tc_inbox_unfollow", `Quick, tc_inbox_unfollow;
- "tc_followers_page_json_raw",`Quick, tc_followers_page_json_raw;
- "tc_followers_page_json", `Quick, tc_followers_page_json;
- "tc_followers_json", `Quick, tc_followers_json;
- "tc_followers_cdb_json", `Quick, tc_followers_cdb_json;
- "Note.tc_of_rfc4287", `Quick, Note.tc_of_rfc4287;
- "Note.tc_create_note_json", `Quick, Note.tc_create_note_json;
- "Note.tc_diluviate", `Quick, Note.tc_diluviate;
- "Note.tc_note_to_plain", `Quick, Note.tc_note_to_plain;
- "tc_create_follow_json", `Quick, tc_create_follow_json;
- "tc_reject_json", `Quick, tc_reject_json;
- "tc_subscribed", `Quick, tc_subscribed;
- "tc_to_rfc4287_0", `Quick, tc_to_rfc4287_0;
- "tc_to_rfc4287_loaded", `Quick, tc_to_rfc4287_loaded;
- "tc_decode_create_notes", `Quick, tc_decode_create_notes;
- ]
- ];
- assert true
|