3 * _| || |_/ ___| ___ _ __ _ __ ___ | |
4 * |_ .. _\___ \ / _ \ '_ \| '_ \ / _ \| |
5 * |_ _|___) | __/ |_) | |_) | (_) |_|
6 * |_||_| |____/ \___| .__/| .__/ \___/(_)
13 * Copyright (C) The #Seppo contributors. All rights reserved.
15 * This program is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation, either version 3 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35 Mirage_crypto_rng_lwt.initialize
(module Mirage_crypto_rng.Fortuna
);
36 Unix.chdir
"../../../test/"
38 let tc_follower_state () =
39 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_follower_state");
40 Ap.Followers.State.(Pending
|> to_string
) |>
41 check
string __LOC__
"pending"
43 let tc_inbox_follow () =
44 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_inbox_follow");
45 let a = "data/follow.mastodon.json"
46 |> File.in_channel
Ezjsonm.from_channel
47 |> As2_vocab.Activitypub.Decode.follow
49 a.id
|> A.equals_uri __LOC__
(Uri.of_string
"https://alpaka.social/afe4ac8a-aaeb-41f5-a348-e5d133bdb931");
50 a.actor
|> A.equals_uri __LOC__
(Uri.of_string
"https://alpaka.social/users/traunstein");
51 a.object_
|> A.equals_uri __LOC__
(Uri.of_string
"https://dev.seppo.social/2023-06-12/activitypub/profile.json");
54 | _
-> "-" |> A.equals_string __LOC__
""
56 let tc_inbox_unfollow () =
57 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_inbox_unfollow");
58 let o = "data/undo-follow.mastodon.json"
59 |> File.in_channel
Ezjsonm.from_channel
60 |> As2_vocab.Activitypub.Decode.(undo follow
)
62 o.id
|> Uri.to_string
|> A.equals_string __LOC__
"https://alpaka.social/users/traunstein#follows/5219/undo";
63 o.actor
|> Uri.to_string
|> A.equals_string __LOC__
"https://alpaka.social/users/traunstein";
64 o.obj
.id
|> Uri.to_string
|> A.equals_string __LOC__
"https://alpaka.social/a5fc3ab5-92f3-4641-a33e-96418e9bec78";
65 o.obj
.object_
|> Uri.to_string
|> A.equals_string __LOC__
"https://dev.seppo.social/2023-06-12/activitypub/profile.json";
66 assert (o.actor
|> Uri.equal
o.obj
.actor
);
68 a.object_ |> A.equals_uri __LOC__ (Uri.of_string "https://dev.seppo.mro.name/2023-06-12/activitypub/profile.json");
71 | _ -> "-" |> A.equals_string __LOC__ ""
75 let tc_followers_page_json_raw () =
76 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_followers_page_json_raw");
78 "1/" |> Uri.of_string
;
79 "2/" |> Uri.of_string
;
80 "3/" |> Uri.of_string
;
81 "4/" |> Uri.of_string
;
82 "5/" |> Uri.of_string
;
84 let base'
= "https://example.com/u/" |> Uri.of_string
in
85 let base = "https://example.com/ap/followers/2.jsa" |> Uri.of_string
in
86 let p : Uri.t
As2_vocab.Types.collection_page
= {
92 last
= Some
(Http.reso ~
base (Uri.of_string
"0.jsa"));
93 next
= Some
(Http.reso ~
base (Uri.of_string
"1.jsa"));
94 part_of
= Some
(Http.reso ~
base (Uri.of_string
"index.jsa"));
95 prev
= Some
(Http.reso ~
base (Uri.of_string
"3.jsa"));
98 p |> As2_vocab.Encode.(collection_page ~
base (uri ~
base:base'
))
99 |> Ezjsonm.value_to_string ~minify
:false
100 |> A.equals_string __LOC__
{|{
102 "https://www.w3.org/ns/activitystreams",
103 "https://w3id.org/security/v1",
105 "schema": "http://schema.org#",
106 "PropertyValue": "schema:PropertyValue",
107 "value": "schema:value",
111 "type": "OrderedCollectionPage",
112 "id": "https://example.com/ap/followers/2.jsa",
113 "current": "https://example.com/ap/followers/2.jsa",
114 "last": "https://example.com/ap/followers/0.jsa",
115 "next": "https://example.com/ap/followers/1.jsa",
116 "partOf": "https://example.com/ap/followers/index.jsa",
117 "prev": "https://example.com/ap/followers/3.jsa",
119 "https://example.com/u/1/",
120 "https://example.com/u/2/",
121 "https://example.com/u/3/",
122 "https://example.com/u/4/",
123 "https://example.com/u/5/"
127 let tc_followers_page_json () =
128 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_followers_page_json");
129 let foo = "https://example.com/foo/usr/" |> Uri.of_string
in
130 let base = "https://example.com/" |> Uri.of_string
in
131 let path = Ap.apub ^
"followers/" in
132 let base = Http.reso ~
base (Uri.make ~
path ()) in
133 [ "1/"; "2/"; "3/"; "4/"; "5/" ]
135 |> List.fold_left
(fun init
path -> (Uri.make ~
path () |> Http.reso ~
base:foo) :: init
) []
136 |> Ap.Followers.Json.to_page_json ~
base path ~is_last
:false 2
137 |> Ezjsonm.value_to_string ~minify
:false
138 |> A.equals_string __LOC__
{|{
140 "https://www.w3.org/ns/activitystreams",
141 "https://w3id.org/security/v1",
143 "schema": "http://schema.org#",
144 "PropertyValue": "schema:PropertyValue",
145 "value": "schema:value",
149 "type": "OrderedCollectionPage",
150 "id": "https://example.com/activitypub/followers/2.jsa",
151 "current": "https://example.com/activitypub/followers/2.jsa",
152 "last": "https://example.com/activitypub/followers/0.jsa",
153 "next": "https://example.com/activitypub/followers/1.jsa",
154 "partOf": "https://example.com/activitypub/followers/index.jsa",
155 "prev": "https://example.com/activitypub/followers/3.jsa",
157 "https://example.com/foo/usr/1/",
158 "https://example.com/foo/usr/2/",
159 "https://example.com/foo/usr/3/",
160 "https://example.com/foo/usr/4/",
161 "https://example.com/foo/usr/5/"
165 let tc_followers_json () =
166 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_followers_json");
167 let foo = "https://example.com/foo/usr/" |> Uri.of_string
in
168 let lst = [ "1/"; "2/"; "3/"; "4/"; "5/" ]
170 |> List.fold_left
(fun init
path -> (Uri.make ~
path () |> Http.reso ~
base:foo) :: init
) []
172 let base = "https://example.com/" |> Uri.of_string
in
173 let path = Ap.apub ^
"followers/" in
174 let base = Http.reso ~
base (Uri.make ~
path ()) in
175 let _ = File.mkdir_p
File.pDir
path in
176 (* let oc = stdout in *)
177 "/dev/null" |> File.out_channel_append
(fun oc ->
178 Ap.Followers.Json.(List.fold_left
179 (fold2pages
3 (flush_page_json ~
base ~
oc path))
182 |> flush_page_json ~
base ~is_last
:true ~
oc path);
183 (* check existence of index.jsa *)
184 (* check existence of 0.jsa *)
185 (* check existence of 1.jsa *)
186 "" |> A.equals_string __LOC__
""
189 let tc_followers_cdb_json () =
190 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_followers_cdb_json");
191 "/dev/null" |> File.out_channel_append
(fun oc ->
192 let base = "https://example.com/" |> Uri.of_string
in
193 let path = Ap.apub ^
"follower2/" in
194 let base = Http.reso ~
base (Uri.make ~
path ()) in
195 let path = "tmp/" ^
path in
196 let _ = File.mkdir_p
File.pDir
path in
197 let _ = Ap.Followers.Json.coll_of_cdb ~
base ~
oc ~pagesize
:3 path (Mapcdb.Cdb
"data/followers.cdb") in
198 "" |> A.equals_string __LOC__
""
202 let tc_of_rfc4287 () =
204 let e = {Entry.empty
with
205 id
= "" |> Uri.of_string
;
208 published
= Rfc3339.T
"2023-10-24T11:12:13+02:00";
209 updated
= Rfc3339.T
"2023-10-24T11:12:13+02:00";
210 links
= [Link.make
("https://Seppo.mro.name/demo" |> Uri.of_string
) ];
213 e.title
|> check
string __LOC__
"Title";
214 let n = e |> Ap.Note.of_rfc4287
in
215 let _,su
= n.summary_map
|> List.hd
in
216 su
|> check
string __LOC__
"Title";
217 n.url
|> List.hd
|> Uri.to_string
|> check
string __LOC__
"https://seppo.mro.name/demo"
219 let tc_create_note_json () =
220 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_create_note_json");
221 "data/create.note.mastodon2.json" |> File.in_channel
(fun ic
->
222 let c : As2_vocab.Types.note
As2_vocab.Types.create
= Ezjsonm.from_channel ic
223 |> As2_vocab.Decode.(create note
)
225 assert (not
c.direct_message
);
227 n.id
|> Uri.to_string
|> A.equals_string __LOC__
"https://bewegung.social/users/mro/statuses/111561416759041219";
228 n.attributed_to
|> Uri.to_string
|> A.equals_string __LOC__
"https://bewegung.social/users/mro";
229 n.published
|> Option.get
|> Ptime.to_rfc3339
|> A.equals_string __LOC__
"2023-12-11T10:55:25-00:00";
230 n.in_reply_to
|> List.length
|> A.equals_int __LOC__
0;
231 assert (n.summary_map
|> List.length
= 0);
232 let _,co
= n.content_map
|> List.hd
in
233 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>|};
234 n.tags
|> List.length
|> A.equals_int __LOC__
3;
237 {ty
=`Mention
;name
=n0
;href
=h0
};
238 {ty
=`Hashtag
;name
=n1
;href
=h1
};
239 {ty
=`Hashtag
;name
=n2
;href
=h2
};
241 n0
|> A.equals_string __LOC__
"@demo@seppo.social";
242 h0
|> Uri.to_string
|> A.equals_string __LOC__
"https://seppo.social/demo/activitypub/profile.jlda";
243 n1
|> A.equals_string __LOC__
"#social";
244 h1
|> Uri.to_string
|> A.equals_string __LOC__
"https://bewegung.social/tags/social";
245 n2
|> A.equals_string __LOC__
"#web";
246 h2
|> Uri.to_string
|> A.equals_string __LOC__
"https://bewegung.social/tags/web";
248 | _ -> failwith
"aua"
253 let tc_diluviate () =
256 id
= "https://example.com/1" |> Uri.of_string
;
258 content_map
= ["de","Inhalt"];
259 summary_map
= ["de","⚠️ Summary"];
260 url
= ["https://Seppo.mro.name/demo" |> Uri.of_string
];
262 let base = Uri.empty
in
263 let minify = false in
266 |> As2_vocab.Encode.note ~
base |> Ezjsonm.value_to_string ~
minify
267 |> Assrt.equals_string
270 "id": "https://example.com/1",
272 "mediaType": "text/html; charset=utf8",
274 "de": "<a href='https://seppo.mro.name/demo'>https://seppo.mro.name/demo</a><br/>\n<br/>\nInhalt"
280 "url": "https://example.com/1"
284 let tc_note_to_plain () =
286 test/data/ap/inbox/create/note/note-OZcAekXDY1A.json
291 let tc_create_follow_json () =
292 let to_actor = "http://example.com/to/actor" |> Uri.of_string
293 and from_actor
= "http://example.com/from/actor" |> Uri.of_string
294 and to_inbox
= "http://example.com/to/inbox" |> Uri.of_string
295 and base = "http://example.com/from/" |> Uri.of_string
296 and tnow
= Ptime.of_date_time
((2024,1,2), ((3,4,5),60*60)) |> Option.value ~default
:Ptime.max
297 and minify = false in
298 let _fo = to_actor |> Ap.Following.make ~tnow ~me
:from_actor ~inbox
:to_inbox
in
300 |> As2_vocab.Encode.follow ~
base
301 |> Ezjsonm.value_to_string ~
minify |>
305 "https://www.w3.org/ns/activitystreams",
306 "https://w3id.org/security/v1",
308 "schema": "http://schema.org#",
309 "PropertyValue": "schema:PropertyValue",
310 "value": "schema:value",
315 "id": "http://example.com/from/actor#subscribe",
316 "actor": "http://example.com/from/actor",
317 "endTime": "2024-04-03T02:04:05Z",
318 "object": "http://example.com/to/actor"
321 let tc_reject_json () =
322 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "test_reject_json");
324 `O
[("@context", `String
"https://www.w3.org/ns/activitystreams");
325 ("type", `String
"Reject");
326 ("actor", `String
(me
|> Uri.to_string
));
327 ("object", `String
(id
|> Uri.to_string
))]
329 let me = "https://example.com/alice" |> Uri.of_string
in
330 let id = match "data/create.note.mastodon2.json" |> File.in_channel
Ezjsonm.from_channel
with
331 | `O
(_ :: ("id", `String
id) :: _) -> id |> Uri.of_string
333 id |> Uri.to_string
|> A.equals_string __LOC__
{|https
://bewegung
.social
/users
/mro
/statuses
/111561416759041219/activity
|};
336 |> Ezjsonm.value_to_string
337 |> 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"}|};
340 let tc_subscribed () =
341 Logr.info
(fun m
-> m
"%s" __LOC__
);
343 try i
|> Printf.sprintf
"/tmp/%d.xml" |> Unix.unlink
344 with | Unix.Unix_error
(Unix.ENOENT
, "unlink", _) -> ()
346 let cdb = Mapcdb.Cdb
"data/2024-04-30-131146-subscribed.cdb" in
348 |> Mapcdb.fold_left
(fun c _ -> 1 + c) 0
349 |> A.equals_int __LOC__
52;
350 let r = Ap.Followers.Atom.rule
in
351 r.target
|> A.equals_string __LOC__
"activitypub/subscribers/index.xml";
352 (match Ap.Followers.Atom.of_cdb
354 ~
base:("https://example.com/" |> Uri.of_string
)
356 ~xsl
:(Rfc4287.xsl
"my.xsl" "./tmp/noop")
357 ~rel
:(Some
Rfc4287.Link.subscribers
)
360 | Error
_ -> failwith __LOC__
362 |> A.equals_string __LOC__
"./tmp/10.xml";
363 "./tmp/0.xml" |> File.to_string
|> A.equals_string __LOC__
{|<?xml version
="1.0"?
>
364 <?xml
-stylesheet
type="text/xsl" href
="../../themes/current/my.xsl"?
>
365 <feed xmlns
="http://www.w3.org/2005/Atom" xml
:base="https://example.com/">
366 <title
>My Title
</title
>
368 <link rel
="self" href
="0.xml" title
="1"/>
369 <link rel
="first" href
="." title
="last"/>
370 <link rel
="last" href
="0.xml" title
="1"/>
371 <link rel
="previous" href
="1.xml" title
="2"/>
372 <link rel
="subscribers" href
="https://social.wohlfarth.name/users/alain" title
=""/>
373 <link rel
="subscribers" href
="https://hci.social/users/sigchi" title
=""/>
374 <link rel
="subscribers" href
="https://fosstodon.org/users/nlnetlabs" title
=""/>
375 <link rel
="subscribers" href
="https://mastodon.xyz/users/NGIZero" title
=""/>
376 <link rel
="subscribers" href
="https://w3c.social/users/w3c" title
=""/>
378 "./tmp/10.xml" |> File.to_string
|> A.equals_string __LOC__
{|<?xml version
="1.0"?
>
379 <?xml
-stylesheet
type="text/xsl" href
="../../themes/current/my.xsl"?
>
380 <feed xmlns
="http://www.w3.org/2005/Atom" xml
:base="https://example.com/">
381 <title
>My Title
</title
>
383 <link rel
="self" href
="10.xml" title
="11"/>
384 <link rel
="first" href
="." title
="last"/>
385 <link rel
="last" href
="0.xml" title
="1"/>
386 <link rel
="previous" href
="11.xml" title
="12"/>
387 <link rel
="next" href
="9.xml" title
="10"/>
388 <link rel
="subscribers" href
="https://mas.to/users/leostera" title
=""/>
389 <link rel
="subscribers" href
="https://social.network.europa.eu/users/EU_Commission" title
="European Commission" rfc7565
="acct:EU_Commission@social.network.europa.eu"/>
391 "?" |> A.equals_string __LOC__
"?"
393 let tc_to_rfc4287_0 () =
394 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "to_rfc4287_0");
395 let now = ((2024,3,19), ((1,2,3),60*60)) |> Ptime.of_date_time
396 and tz
= Timedesc.Time_zone.utc
in
397 let n = {Ap.Note.empty
with
398 id = "https://example.com/o/42" |> Uri.of_string
;
399 attributed_to
= "https://example.com/a/23" |> Uri.of_string
;
400 content_map
= ["en","Some Content"];
402 summary_map
= ["en","No content warning"];
404 let now = now |> Option.value ~default
:Ptime.epoch
in
405 let a = n |> Ap.Note.to_rfc4287 ~tz ~
now in
406 a.id |> Uri.to_string
|> Assrt.equals_string __LOC__
"https://example.com/o/42";
407 a.author
.uri
|> Option.value ~default
:Uri.empty
|> Uri.to_string
|> Assrt.equals_string __LOC__
"https://example.com/a/23";
408 let Rfc3339.T t
= a.published
in
409 t
|> Assrt.equals_string __LOC__
"2024-03-19T00:02:03Z";
410 a.title
|> Assrt.equals_string __LOC__
"No content warning";
411 a.content
|> Assrt.equals_string __LOC__
"Some Content";
414 let tc_to_rfc4287_loaded () =
415 Logr.info
(fun m
-> m
"%s.%s" "Ap_test" "to_rfc4287_loaded");
417 let fn = "data/ap/inbox/create/note/" ^
fn in
421 match ic
|> Ezjsonm.from_channel
|> As2_vocab.Activitypub.Decode.obj
with
422 | Error
_ -> failwith
"failed to load note"
423 | Ok
o -> match o with
424 | `Create
{ obj
= `Note obj
; _ } -> obj
425 | _ -> failwith
"strange type")
427 let now = ((2024,3,19), ((1,2,3),60*60)) |> Ptime.of_date_time
|> Option.get
428 and tz
= Timedesc.Time_zone.utc
429 and base = "https://example.com/fe/" |> Uri.of_string
430 and attr
= [ ((Xmlm.ns_xmlns
,"xmlns"),Xml.ns_a
);
431 ((Xmlm.ns_xmlns
,"thr") ,Xml.ns_thr
);
432 ((Xmlm.ns_xmlns
,"as") ,Xml.ns_as
);
433 ((Xmlm.ns_xmlns
,"wf") ,Xml.ns_rfc7033
); ] in
434 let apu = load_note "note-Hjcb9bqwCgk.json" in
435 let ato = apu |> Ap.Note.to_rfc4287 ~tz ~
now in
436 ato.author
.name
|> Assrt.equals_string __LOC__
"https://mastodon.social/users/nicholas_saunders";
437 ato.author
.uri
|> Option.value ~default
:Uri.empty
|> Uri.to_string
|> Assrt.equals_string __LOC__
"https://mastodon.social/users/nicholas_saunders";
438 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.
440 I'm inferring that this has something
to with the Goat
, but have no idea
. Guess I'll never know what it was about
.
442 [1]: https
://mastodon
.social
/tags
/alaqsaflood
|};
443 let buf = 1024 |> Buffer.create
in
444 buf |> Xml.to_buf
(ato |> Rfc4287.Entry.to_atom ~attr ~
base);
445 buf |> Buffer.to_bytes
|> Bytes.to_string
|> Assrt.equals_string __LOC__
{|<?xml version
="1.0"?
>
446 <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">
447 <id>https
://mastodon
.social
/users
/nicholas_saunders
/statuses
/112615088973179734</id>
448 <title
type="text"></title
>
449 <updated
>2024-06-14T12
:58:07Z
</updated
>
450 <published
>2024-06-14T12
:58:07Z
</published
>
451 <as:sensitive
>false</as:sensitive
>
453 <name
>https
://mastodon
.social
/users
/nicholas_saunders
</name
>
455 <uri
>https
://mastodon
.social
/users
/nicholas_saunders
</uri
></author
>
456 <link rel
="self" href
="https://mastodon.social/users/nicholas_saunders/statuses/112615088973179734"/>
457 <thr
:in-reply
-to ref="https://floss.social/users/wschenk/statuses/112615060106830322"/>
458 <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.
460 I'm inferring that this has something
to with the Goat
, but have no idea
. Guess I'll never know what it was about
.
462 [1]: https
://mastodon
.social
/tags
/alaqsaflood
</content
>
465 let apu : As2_vocab.Types.note
= load_note "note-OiqQGte9TSY.json" in
466 (match apu.in_reply_to
with
467 | [ u
] -> u
|> Uri.to_string
|> Assrt.equals_string __LOC__
{|https
://infosec
.exchange
/users
/womble
/statuses
/112948594753912420|}
468 | _ -> failwith __LOC__
);
469 let ato : Rfc4287.Entry.t
= apu |> Ap.Note.to_rfc4287 ~tz ~
now in
470 apu.in_reply_to
|> List.length
|> Assrt.equals_int __LOC__
1;
471 ato.in_reply_to
|> List.length
|> Assrt.equals_int __LOC__
(apu.in_reply_to
|> List.length
);
473 buf |> Xml.to_buf
(ato |> Rfc4287.Entry.to_atom ~attr ~
base);
474 buf |> Buffer.to_bytes
|> Bytes.to_string
|> Assrt.equals_string __LOC__
{|<?xml version
="1.0"?
>
475 <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">
476 <id>https
://benjojo
.co
.uk
/u
/benjojo
/h
/89L5knBH
4TGG
4qY
4VT
</id>
477 <title
type="text"></title
>
478 <updated
>2024-08-12T10
:40:45Z
</updated
>
479 <published
>2024-08-12T10
:40:45Z
</published
>
480 <as:sensitive
>false</as:sensitive
>
483 <wf
:uri
>acct
:benjojo
@benjojo
.co
.uk
</wf
:uri
>
484 <uri
>https
://benjojo
@benjojo
.co
.uk
/u
/benjojo
</uri
></author
>
485 <link rel
="self" href
="https://benjojo.co.uk/u/benjojo/h/89L5knBH4TGG4qY4VT"/>
486 <thr
:in-reply
-to ref="https://infosec.exchange/users/womble/statuses/112948594753912420"/>
487 <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
>
491 let tc_create_note () =
492 let base = "https://example.org/" |> Uri.of_string
in
493 let n = {Ap.Note.empty
with
494 id = "note-42" |> Uri.of_string
|> Http.reso ~
base;
495 attributed_to
= "alice" |> Uri.of_string
|> Http.reso ~
base;
496 to_
= [As2_vocab.Constants.ActivityStreams.public
];
497 cc
= ["activitypub/subscribers/index.jsa" |> Uri.of_string
|> Http.reso ~
base]} in
498 let c = n |> Ap.Note.Create.make
in
500 |> List.map
Uri.to_string
|> Astring.String.concat ~sep
:" "
501 |> check
string __LOC__
"https://www.w3.org/ns/activitystreams#Public";
503 |> List.map
Uri.to_string
|> Astring.String.concat ~sep
:" "
504 |> check
string __LOC__
"https://example.org/activitypub/subscribers/index.jsa";
506 |> List.map
Uri.to_string
|> Astring.String.concat ~sep
:" "
507 |> check
string __LOC__
"https://www.w3.org/ns/activitystreams#Public";
509 |> List.map
Uri.to_string
|> Astring.String.concat ~sep
:" "
510 |> check
string __LOC__
"https://example.org/activitypub/subscribers/index.jsa";
512 |> As2_vocab.Encode.(create ~lang
:As2_vocab.Constants.ActivityStreams.und ~
base (note ~
base))
513 |> Ezjsonm.value_to_string ~
minify:false
514 |> A.equals_string __LOC__
{|{
516 "https://www.w3.org/ns/activitystreams",
517 "https://w3id.org/security/v1",
519 "schema": "http://schema.org#",
520 "PropertyValue": "schema:PropertyValue",
521 "value": "schema:value",
526 "id": "https://example.org/note-42#Create",
527 "actor": "https://example.org/alice",
528 "to": "https://www.w3.org/ns/activitystreams#Public",
529 "cc": "https://example.org/activitypub/subscribers/index.jsa",
530 "directMessage": false,
533 "id": "https://example.org/note-42",
534 "attributedTo": "https://example.org/alice",
535 "to": "https://www.w3.org/ns/activitystreams#Public",
536 "cc": "https://example.org/activitypub/subscribers/index.jsa",
537 "mediaType": "text/html; charset=utf8",
543 let tc_decode_create_notes () =
544 Logr.info
(fun m
-> m
"%s" __LOC__
);
545 let dir = "data/ap/inbox/create/note/" in
546 let l : As2_vocab.Types.note list
=
551 let j = f |> File.in_channel
Ezjsonm.from_channel
in
552 (match j |> As2_vocab.Activitypub.Decode.obj
with
553 | Ok `Update
{ obj
= `Note obj
; _ }
554 | Ok `Create
{ obj
= `Note obj
; _ } -> obj
:: init
556 Logr.debug
(fun m
-> m
"%s %s no!" "decode_create_notes" f);
560 Logr.debug
(fun m
-> m
"%s %s ouch! %s" "decode_create_notes" f (Printexc.to_string
e));
563 l |> List.length
|> Assrt.equals_int __LOC__
204;
564 let now = ((2024,3,19), ((1,2,3),60*60)) |> Ptime.of_date_time
|> Option.value ~default
:Ptime.epoch
in
565 let tz = Timedesc.Time_zone.make
"Europe/Amsterdam" |> Option.value ~default
:Timedesc.Time_zone.utc
in
566 let l = l |> List.map
(Ap.Note.to_rfc4287 ~
tz ~
now) in
567 l |> List.length
|> Assrt.equals_int __LOC__
204;
568 let l = l |> List.sort
Rfc4287.Entry.compare
in
569 let l = l |> List.filteri
(fun i
_ -> i
< 2) in
570 let x = l |> Rfc4287.Feed.to_atom
571 ~
base:(Uri.of_string
"http://example.com/")
572 ~self
:(Uri.of_string
"seppo.cgi/p-37/")
575 ~first
:(Uri.of_string
"seppo.cgi/p-37/")
576 ~last
:(Uri.of_string
"seppo.cgi/p-0/")
578 ~updated
:(Rfc3339.T
"2024-06-19 16:15:14+02:00")
579 ~lang
:(Rfc4287.Rfc4646
"de")
580 ~author
:{Rfc4287.Person.empty
with
582 uri
= Some
("alice@example.com" |> Uri.of_string
)} in
583 let fn = "./tmp/as2_vocab_text.dat" in
584 (try fn |> Unix.unlink
with _ -> ());
585 fn |> File.out_channel_replace
(x |> Xml.to_chan ~xsl
:(Rfc4287.xsl
"posts.xsl" fn));
586 (match fn |> File.cat
with
587 | Error
_ -> failwith __LOC__
589 |> Assrt.equals_string __LOC__
{|<?xml version
="1.0"?
>
590 <?xml
-stylesheet
type="text/xsl" href
="../../themes/current/posts.xsl"?
>
591 <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/">
592 <id>http
://example
.com
/seppo
.cgi
/p-37/</id>
593 <title
type="text">ti
</title
>
594 <updated
>2024-06-19 16:15:14+02:00</updated
>
595 <generator uri
="Seppo.mro.name">Seppo
- Personal Social Web
</generator
>
596 <link rel
="self" href
="seppo.cgi/p-37/" title
="38"/>
597 <link rel
="first" href
="seppo.cgi/p-37/" title
="last"/>
598 <link rel
="last" href
="seppo.cgi/p-0/" title
="1"/>
599 <entry xml
:lang
="en">
600 <id>https
://mastodon
.social
/users
/nicholas_saunders
/statuses
/112608234771751001</id>
601 <title
type="text"></title
>
602 <updated
>2024-06-13T09
:55:01+02:00</updated
>
603 <published
>2024-06-13T09
:55:01+02:00</published
>
604 <as:sensitive
>false</as:sensitive
>
606 <name
>https
://mastodon
.social
/users
/nicholas_saunders
</name
>
608 <uri
>https
://mastodon
.social
/users
/nicholas_saunders
</uri
></author
>
609 <link rel
="self" href
="https://mastodon.social/users/nicholas_saunders/statuses/112608234771751001"/>
610 <thr
:in-reply
-to ref="https://infosec.exchange/users/SpaceLifeForm/statuses/112608204971110992"/>
611 <content
type="text">@SpaceLifeForm
@infosec
.exchange
@RickiTarr
@beige
.party I'll be here all day
@SpaceLifeForm
@infosec
.exchange
:)
613 (not really
.)</content
>
615 <entry xml
:lang
="en">
616 <id>https
://mastodon
.social
/users
/nicholas_saunders
/statuses
/112606941257663038</id>
617 <title
type="text"></title
>
618 <updated
>2024-06-13T04
:26:03+02:00</updated
>
619 <published
>2024-06-13T04
:26:03+02:00</published
>
620 <as:sensitive
>false</as:sensitive
>
622 <name
>https
://mastodon
.social
/users
/nicholas_saunders
</name
>
624 <uri
>https
://mastodon
.social
/users
/nicholas_saunders
</uri
></author
>
625 <link rel
="self" href
="https://mastodon.social/users/nicholas_saunders/statuses/112606941257663038"/>
626 <thr
:in-reply
-to ref="https://mastodon.social/users/thejapantimes/statuses/112606642206596379"/>
627 <content
type="text">@thejapantimes
@mastodon
.social so
then #hamas
[1] didn't accept the offer
, but rather seeks different terms
.
629 [1]: https
://mastodon
.social
/tags
/hamas
</content
>
637 "set_up", `Quick
, set_up;
638 "tc_follower_state", `Quick
, tc_follower_state;
639 "tc_inbox_follow", `Quick
, tc_inbox_follow;
640 "tc_inbox_unfollow", `Quick
, tc_inbox_unfollow;
641 "tc_followers_page_json_raw",`Quick
, tc_followers_page_json_raw;
642 "tc_followers_page_json", `Quick
, tc_followers_page_json;
643 "tc_followers_json", `Quick
, tc_followers_json;
644 "tc_followers_cdb_json", `Quick
, tc_followers_cdb_json;
645 "Note.tc_of_rfc4287", `Quick
, Note.tc_of_rfc4287;
646 "Note.tc_create_note_json", `Quick
, Note.tc_create_note_json;
647 "Note.tc_diluviate", `Quick
, Note.tc_diluviate;
648 "Note.tc_note_to_plain", `Quick
, Note.tc_note_to_plain;
649 "tc_create_follow_json", `Quick
, tc_create_follow_json;
650 "tc_reject_json", `Quick
, tc_reject_json;
651 "tc_subscribed", `Quick
, tc_subscribed;
652 "tc_to_rfc4287_0", `Quick
, tc_to_rfc4287_0;
653 "tc_to_rfc4287_loaded", `Quick
, tc_to_rfc4287_loaded;
654 "tc_create_note", `Quick
, tc_create_note;
655 "tc_decode_create_notes", `Quick
, tc_decode_create_notes;