Merge pull request #15596 from annando/atproto
The AT Protocol handling is now less Bluesky centric
|
|
@ -1,6 +1,6 @@
|
|||
# Konnektoren installieren
|
||||
|
||||
Friendica verwendet Konnektoren, um sich mit einigen Netzwerken zu verbinden, wie Tumblr oder Bluesky.
|
||||
Friendica verwendet Konnektoren, um sich mit einigen Netzwerken zu verbinden, wie Tumblr oder den auf dem AT Protokoll basierenden Systemen wie Bluesky, Eurosky oder Blacksky.
|
||||
|
||||
Alle diese Konnektoren erfordern einen Account im Zielnetzwerk.
|
||||
Außerdem musst du (oder die Server-Administration) in der Regel einen API-Schlüssel erhalten, um die Verbindung zu ermöglichen.
|
||||
|
|
@ -12,16 +12,16 @@ Dies geschieht über die Server-Verwaltung.
|
|||
|
||||
Einige der Konnektoren erfordern auch einen „API-Schlüssel“ des Dienstes, mit dem du dich verbinden möchtest.
|
||||
Für Tumblr findet man diese Informationen auf den Seiten der Server-Verwaltung, während für Twitter (X) jede Person einen eigenen API-Schlüssel erstellen muss.
|
||||
Andere Konnektoren, wie Bluesky, benötigen überhaupt keinen API-Schlüssel.
|
||||
Andere Konnektoren, wie das AT Protokoll, benötigen überhaupt keinen API-Schlüssel.
|
||||
|
||||
Weitere Informationen zu den spezifischen Anforderungen findest du auf der Einstellungsseite des jeweiligen Addons, entweder auf der Verwaltungsseite oder auf der Benutzerseite.
|
||||
|
||||
## Bluesky Jetstream
|
||||
## AT Protokoll Jetstream
|
||||
|
||||
Um die Konnektivität mit Bluesky weiter zu verbessern, kann die „Jetstream“-Konnektivität aktiviert werden.
|
||||
Jetstream ist ein Dienst, der sich mit dem Bluesky-Firehose verbindet.
|
||||
Um die Konnektivität über das AT Protokoll weiter zu verbessern, kann die „Jetstream“-Konnektivität aktiviert werden.
|
||||
Jetstream ist ein Dienst, der sich mit einer AT Protokoll-Firehose verbindet.
|
||||
Mit Jetstream kommen die Nachrichten in Echtzeit an und müssen nicht erst abgefragt werden.
|
||||
Es ermöglicht auch die Echtzeitverarbeitung von Blöcken oder Tracking-Aktivitäten, die über die Bluesky-Website oder -Anwendung durchgeführt werden.
|
||||
Es ermöglicht auch die Echtzeitverarbeitung von Blöcken oder Tracking-Aktivitäten, die über eine AT Protokoll-Website oder -Anwendung durchgeführt werden.
|
||||
|
||||
Um die Jetstream-Verarbeitung zu aktivieren, führe `bin/console.php daemon' über die Befehlszeile aus.
|
||||
Du musst vorher die Prozess-ID-Datei in local.config.php im Abschnitt „jetstream“ mit dem Schlüssel „pidfile“ definieren.
|
||||
|
|
|
|||
|
|
@ -78,9 +78,9 @@ Alternativen werden durch "|" dargestellt.
|
|||
* network:dspr | network:diaspora - Das Diaspora-Protokoll wird hauptsächlich von Diaspora selbst genutzt. Ein paar andere Systeme unterstützen dieses Protokoll ebenfalls, wie Hubzilla, Socialhome or Ganggo.
|
||||
* network:feed - RSS/Atom feeds
|
||||
* network:mail - Mails die via IMAP importiert worden sind.
|
||||
* network:dscs | network:discourse - Beiträge, die über den Discourse connector empfangen werden.
|
||||
* network:tmbl | network:tumblr - Beiträge, die über den Tumblr connector empfangen werden.
|
||||
* network:bsky | network:bluesky - Beiträge, die über den Bluesky connector empfangen werden.
|
||||
* network:dscs | network:discourse - Beiträge, die über den Discourse Connector empfangen werden.
|
||||
* network:tmbl | network:tumblr - Beiträge, die über den Tumblr Connector empfangen werden.
|
||||
* network:bsky | network:bluesky - Beiträge, die über den AT Protokoll Connector empfangen werden.
|
||||
* platform - Benutze dies, um Plattformen in deinen Kanal einzuschließen, oder von ihm auszuschließen, d.h. "+platform:friendica". Im Falle eines Gruppen-Postings enthält der Suchtext beides, die Plattform des Gruppen-Servers und die Plattform des Autors.
|
||||
* visibility - Du hast die Wahl zwischen verschiedenen Sichtbarkeiten. Du kannst nur die ungelisteten oder privaten Beiträge sehen, zu denen du Zugang hast.
|
||||
* visibility:public - (öffentlich)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Konnektoren (Connectors)
|
||||
|
||||
Konnektoren erlauben es Dir, Dich mit anderen sozialen Netzwerken zu verbinden.
|
||||
Mit diesen Konnektoren kannst Du z.B. zu Bluesky, Tumblr oder Twitter posten.
|
||||
Für Bluesky und Tumblr gibt es eine bidirektionale Verbindung, d.h. du kannst Friendica nutzen, um deine Timeline von diesen Diensten zu lesen.
|
||||
Mit diesen Konnektoren kannst Du z.B. über das AT Protokoll mit Bluesky, Eurosky oder Blacksky verbinden oder zu Tumblr oder Twitter posten.
|
||||
Für das AT Protokoll und Tumblr gibt es eine bidirektionale Verbindung, d.h. du kannst Friendica nutzen, um deine Timeline von diesen Diensten zu lesen.
|
||||
Außerdem gibt es einen Konnektor, um Deinen Email-Posteingang zu nutzen.
|
||||
Wenn Du keinen eigenen Knoten betreibst und wissen willst, ob der Server Deiner Wahl diese Konnektoren installiert hat, kannst Du Dich darüber auf der Seite '<domain_des_friendica-servers>/friendica' informieren.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Installing Connectors
|
||||
|
||||
Friendica uses add-ons to connect to some networks, such as Tumblr or Bluesky.
|
||||
Friendica uses add-ons to connect to some networks, such as Tumblr or AT Protocol based systems like Bluesky, Eurosky or Blacksky.
|
||||
|
||||
All of these add-ons require an account on the target network.
|
||||
In addition, you (or usually the server administrator) will need to obtain an API key to allow authenticated access to your Friendica server.
|
||||
|
|
@ -12,16 +12,16 @@ This is done through the site administration panel.
|
|||
|
||||
Some of the connectors also require an "API key" from the service you wish to connect to.
|
||||
For Tumblr, this information can be found in the site administration pages, while for Twitter (X) each user has to create their own API key.
|
||||
Other connectors, such as Bluesky, don't require an API key at all.
|
||||
Other connectors, such as the AT Protocol, don't require an API key at all.
|
||||
|
||||
You can find more information about specific requirements on each addon's settings page, either on the admin page or the user page.
|
||||
|
||||
## Bluesky Jetstream
|
||||
## AT Protocol Jetstream
|
||||
|
||||
To further improve connectivity to Bluesky, Admins can choose to enable 'Jetstream' connectivity.
|
||||
Jetstream is a service that connects to the Bluesky firehose.
|
||||
To further improve connectivity via the AT Protocol, Admins can choose to enable 'Jetstream' connectivity.
|
||||
Jetstream is a service that connects to an AT Protocol firehose.
|
||||
With Jetstream, messages arrive in real time rather than having to be polled.
|
||||
It also enables real-time processing of blocks or tracking activities performed by the user via the Bluesky website or application.
|
||||
It also enables real-time processing of blocks or tracking activities performed by the user via an AT Protocol website or application.
|
||||
|
||||
To enable Jetstream processing, run `bin/console.php jetstream' from the command line.
|
||||
You will need to define the process id file in local.config.php in the 'jetstream' section using the key 'pidfile'.
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ Hook data:
|
|||
|
||||
### follow
|
||||
|
||||
Called before adding a new contact for a user to handle non-native network remote contact (like Bluesky).
|
||||
Called before adding a new contact for a user to handle non-native network remote contact (like the AT Protocol).
|
||||
|
||||
Hook data:
|
||||
|
||||
|
|
@ -610,7 +610,7 @@ Hook data:
|
|||
|
||||
### unfollow
|
||||
|
||||
Called when unfollowing a remote contact on a non-native network (like Bluesky)
|
||||
Called when unfollowing a remote contact on a non-native network (like the AT Protocol)
|
||||
|
||||
Hook data:
|
||||
- **contact** (input): the target public contact (uid = 0) array.
|
||||
|
|
@ -619,7 +619,7 @@ Hook data:
|
|||
|
||||
### revoke_follow
|
||||
|
||||
Called when making a remote contact on a non-native network (like Bluesky) unfollow you.
|
||||
Called when making a remote contact on a non-native network (like the AT Protocol) unfollow you.
|
||||
|
||||
Hook data:
|
||||
- **contact** (input): the target public contact (uid = 0) array.
|
||||
|
|
@ -628,7 +628,7 @@ Hook data:
|
|||
|
||||
### block
|
||||
|
||||
Called when blocking a remote contact on a non-native network (like Bluesky).
|
||||
Called when blocking a remote contact on a non-native network (like the AT Protocol).
|
||||
|
||||
Hook data:
|
||||
- **contact** (input): the remote contact (uid = 0) array.
|
||||
|
|
@ -637,7 +637,7 @@ Hook data:
|
|||
|
||||
### unblock
|
||||
|
||||
Called when unblocking a remote contact on a non-native network (like Bluesky).
|
||||
Called when unblocking a remote contact on a non-native network (like the AT Protocol).
|
||||
|
||||
Hook data:
|
||||
- **contact** (input): the remote contact (uid = 0) array.
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ Alternatives are presented with "|".
|
|||
* network:mail - Mails that had been imported via IMAP.
|
||||
* network:dscs | network:discourse - Posts that are received by the Discourse connector.
|
||||
* network:tmbl | network:tumblr - Posts that are received by the Tumblr connector.
|
||||
* network:bsky | network:bluesky - Posts that are received by the Bluesky connector.
|
||||
* network:bsky | network:bluesky - Posts that are received by the AT Protocol connector.
|
||||
* platform - Use this to include or exclude some platforms from your channel, e.g. "+platform:friendica". In the case of group postings, the search text contains both the platform of the group server and the author's platform.
|
||||
* visibility - You have the choice between different visibilities. You can only see unlisted or private posts that you have the access for.
|
||||
* visibility:public
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Connectors
|
||||
|
||||
Connectors allow you to connect with external social networks and services.
|
||||
They are only required for posting to existing accounts on for example Bluesky, Tumblr or Twitter.
|
||||
For Bluesky and Tumblr you can also enable a bidirectional synchronisation, so that you can use Friendica to read your timeline from Tumblr or Bluesky.
|
||||
They are only required for posting to existing accounts on for example systems that use the AT Protocol (Bluesky, Eurosky, Blacksky), Tumblr or Twitter.
|
||||
For the AT Protocol and Tumblr you can also enable a bidirectional synchronisation, so that you can use Friendica to read your timeline from Tumblr or an AT Protocol based system.
|
||||
There is also a connector for accessing your email INBOX.
|
||||
|
||||
# Instructions For Connecting To People On Specific Services
|
||||
|
|
|
|||
BIN
images/500px-AT_Protocol_logo.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
2
images/500px-AT_Protocol_logo.png.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: Bluesky Social https://commons.wikimedia.org/wiki/File:AT_Protocol_logo.png
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
37
images/platforms/black/atprotocol.svg
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="27"
|
||||
height="27"
|
||||
fill="#000000"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<path
|
||||
d="M13.482 27q-2.934 0-5.4-.972t-4.284-2.754A12.25 12.25 0 0 1 .99 19.116Q0 16.722 0 13.914q0-3.348 1.026-5.94 1.044-2.592 2.88-4.356A12.5 12.5 0 0 1 8.19.918Q10.638 0 13.428 0q3.42 0 5.994 1.062t4.284 2.88A11.7 11.7 0 0 1 26.244 8.1q.828 2.322.756 4.86-.09 3.492-1.458 5.364-1.368 1.854-4.248 1.854a5.84 5.84 0 0 1-2.826-.702 3.7 3.7 0 0 1-1.764-2.07l1.044.054q-.738 1.386-2.016 1.944a6.5 6.5 0 0 1-2.61.558q-1.818 0-3.204-.774a5.7 5.7 0 0 1-2.178-2.214q-.792-1.422-.792-3.294 0-1.926.828-3.33a5.77 5.77 0 0 1 2.232-2.196q1.404-.774 3.168-.774 1.17 0 2.43.486 1.278.486 1.98 1.368l-.738.936V7.884h2.412l-.054 6.462q0 1.386.54 2.088t1.602.702q.936 0 1.44-.522.522-.54.72-1.458a10.7 10.7 0 0 0 .252-2.106q.054-2.79-.828-4.698t-2.394-3.078a9.5 9.5 0 0 0-3.294-1.71q-1.8-.54-3.582-.54-2.52 0-4.482.81-1.962.792-3.312 2.25-1.332 1.44-2.016 3.42-.666 1.962-.63 4.32.072 2.34.846 4.212a9.3 9.3 0 0 0 2.16 3.204 9.4 9.4 0 0 0 3.276 2.034q1.89.702 4.14.702 1.26 0 2.502-.288 1.26-.27 2.304-.774l1.026 2.808q-1.386.648-2.916.954a14.7 14.7 0 0 1-3.078.324m-.144-10.098q1.278 0 2.142-.738t.864-2.502q0-1.602-.774-2.412-.756-.828-2.142-.828-1.638 0-2.448.864t-.81 2.376q0 1.548.828 2.394.846.846 2.34.846" />
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by/4.0/" />
|
||||
<dc:source>https://commons.wikimedia.org/wiki/File:AT_Protocol_Logo.svg</dc:source>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
2
images/platforms/black/atprotocol.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: Derived from https://commons.wikimedia.org/wiki/File:AT_Protocol_Logo.svg
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
6
images/platforms/black/blacksky.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.0620117 0.348442 87.9941 74.9653">
|
||||
<path d="M41.9565 74.9643L24.0161 74.9653L41.9565 74.9643ZM63.8511 74.9653H45.9097L63.8501 74.9643V57.3286H63.8511V74.9653ZM45.9097 44.5893C45.9099 49.2737 49.7077 53.0707 54.3921 53.0707H63.8501V57.3286H54.3921C49.7077 57.3286 45.9099 61.1257 45.9097 65.81V74.9643H41.9565V65.81C41.9563 61.1258 38.1593 57.3287 33.4751 57.3286H24.0161V53.0707H33.4741C38.1587 53.0707 41.9565 49.2729 41.9565 44.5883V35.1303H45.9097V44.5893ZM63.8511 53.0707H63.8501V35.1303H63.8511V53.0707Z" fill="black"></path>
|
||||
<path d="M52.7272 9.83198C49.4148 13.1445 49.4148 18.5151 52.7272 21.8275L59.4155 28.5158L56.4051 31.5262L49.7169 24.8379C46.4044 21.5254 41.0338 21.5254 37.7213 24.8379L31.2482 31.3111L28.4527 28.5156L34.9259 22.0424C38.2383 18.7299 38.2383 13.3594 34.9259 10.0469L28.2378 3.35883L31.2482 0.348442L37.9365 7.03672C41.2489 10.3492 46.6195 10.3492 49.932 7.03672L56.6203 0.348442L59.4155 3.14371L52.7272 9.83198Z" fill="black"/>
|
||||
<path d="M24.3831 23.2335C23.1706 27.7584 25.8559 32.4095 30.3808 33.6219L39.5172 36.07L38.4154 40.182L29.2793 37.734C24.7544 36.5215 20.1033 39.2068 18.8909 43.7317L16.5215 52.5745L12.7028 51.5513L15.0721 42.7088C16.2846 38.1839 13.5993 33.5328 9.07434 32.3204L-0.0620117 29.8723L1.03987 25.76L10.1762 28.2081C14.7011 29.4206 19.3522 26.7352 20.5647 22.2103L23.0127 13.074L26.8311 14.0971L24.3831 23.2335Z" fill="black"/>
|
||||
<path d="M67.3676 22.0297C68.5801 26.5546 73.2311 29.2399 77.756 28.0275L86.8923 25.5794L87.9941 29.6914L78.8578 32.1394C74.3329 33.3519 71.6476 38.003 72.86 42.5279L75.2294 51.3707L71.411 52.3938L69.0417 43.5513C67.8293 39.0264 63.1782 36.3411 58.6533 37.5535L49.5169 40.0016L48.415 35.8894L57.5514 33.4413C62.0763 32.2288 64.7616 27.5778 63.5492 23.0528L61.1011 13.9165L64.9195 12.8934L67.3676 22.0297Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
2
images/platforms/black/blacksky.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: https://commons.wikimedia.org/wiki/File:Blacksky_Algorithms_Logo_(black).svg
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
82
images/platforms/black/eurosky.svg
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 461 510" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||
<g transform="matrix(1,0,0,1,128.375,27.0069)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:black;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:black;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,67.5926,221.36)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:black;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,374.121,172.829)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:black;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,202.563,-210.015)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:black;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,380.732,-81.8617)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:black;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.759576,-2.35171,0.365844,0.118164,-102.007,679.384)">
|
||||
<path d="M120.752,330.756L173.954,330.756C173.714,340.398 173.702,350.374 173.944,360.361L121.004,360.361C121.159,350.66 121.083,340.686 120.752,330.756Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.759576,-2.35171,0.365844,0.118164,-102.007,679.384)">
|
||||
<path d="M120.752,329.456L173.954,329.456C174.013,329.456 174.07,329.623 174.108,329.912C174.147,330.202 174.163,330.586 174.154,330.962C173.917,340.472 173.905,350.31 174.144,360.161C174.153,360.536 174.136,360.919 174.098,361.207C174.06,361.496 174.003,361.662 173.944,361.662L121.004,361.662C120.946,361.662 120.892,361.506 120.853,361.233C120.815,360.959 120.796,360.594 120.802,360.228C120.955,350.659 120.881,340.822 120.554,331.029C120.542,330.645 120.557,330.244 120.595,329.939C120.633,329.633 120.691,329.456 120.752,329.456ZM121,332.057C121.278,341.113 121.347,350.192 121.226,359.061C121.226,359.061 173.71,359.061 173.71,359.061C173.512,349.957 173.521,340.877 173.719,332.057L121,332.057Z"/>
|
||||
</g>
|
||||
<g transform="matrix(2.99645,1.73569,-0.192701,0.332673,-79.3508,-17.2321)">
|
||||
<path d="M176.303,360.361L114.623,360.361C114.865,350.716 114.943,340.724 114.844,330.756L176.361,330.756C176.173,340.462 176.15,350.453 176.303,360.361Z"/>
|
||||
</g>
|
||||
<g transform="matrix(2.99645,1.73569,-0.192701,0.332673,-79.3508,-17.2321)">
|
||||
<path d="M176.303,361.662L114.623,361.662C114.579,361.662 114.537,361.482 114.51,361.173C114.482,360.864 114.472,360.46 114.482,360.074C114.721,350.56 114.798,340.703 114.701,330.871C114.697,330.508 114.711,330.147 114.738,329.878C114.765,329.609 114.804,329.456 114.844,329.456L176.361,329.456C176.404,329.456 176.444,329.625 176.472,329.919C176.499,330.213 176.511,330.602 176.504,330.98C176.318,340.554 176.295,350.409 176.446,360.182C176.452,360.555 176.44,360.931 176.412,361.215C176.385,361.499 176.345,361.662 176.303,361.662ZM176.139,359.061C176.015,350.022 176.035,340.931 176.191,332.057C172.647,332.057 115.001,332.057 115.001,332.057C115.076,341.143 115.007,350.236 114.802,359.061L176.139,359.061Z"/>
|
||||
</g>
|
||||
<g transform="matrix(1.036,0.23923,-0.0865007,0.374596,-16.6075,98.5597)">
|
||||
<path d="M117.078,330.756L172.417,330.756C171.947,340.383 172.006,350.349 172.66,360.361L117.606,360.361C117.983,350.708 117.828,340.743 117.078,330.756Z"/>
|
||||
</g>
|
||||
<g transform="matrix(1.036,0.23923,-0.0865007,0.374596,-16.6075,98.5597)">
|
||||
<path d="M117.078,329.456L172.417,329.456C172.553,329.456 172.682,329.618 172.771,329.9C172.86,330.183 172.901,330.558 172.883,330.93C172.42,340.425 172.478,350.255 173.123,360.13C173.148,360.51 173.11,360.9 173.021,361.195C172.932,361.491 172.799,361.662 172.66,361.662L117.606,361.662C117.472,361.662 117.345,361.505 117.256,361.23C117.167,360.956 117.124,360.589 117.138,360.222C117.51,350.7 117.358,340.871 116.617,331.021C116.589,330.638 116.624,330.239 116.713,329.935C116.802,329.632 116.936,329.456 117.078,329.456ZM117.651,332.057C118.28,341.159 118.422,350.232 118.126,359.061C118.126,359.061 172.102,359.061 172.102,359.061C171.56,349.938 171.504,340.864 171.883,332.057L117.651,332.057Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.891455,-2.76001,0.365844,0.118164,-52.8187,518.104)">
|
||||
<path d="M175.685,360.361L115.21,360.361C115.311,350.635 115.215,340.662 114.9,330.756L175.749,330.756C175.526,340.383 175.497,350.359 175.685,360.361Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.891455,-2.76001,0.365844,0.118164,-52.8187,518.104)">
|
||||
<path d="M175.685,361.662L115.21,361.662C115.161,361.662 115.116,361.51 115.083,361.244C115.05,360.978 115.034,360.621 115.038,360.259C115.138,350.666 115.043,340.829 114.733,331.059C114.72,330.672 114.732,330.264 114.765,329.951C114.798,329.638 114.847,329.456 114.9,329.456L175.749,329.456C175.8,329.456 175.848,329.625 175.881,329.919C175.914,330.213 175.927,330.602 175.919,330.98C175.699,340.475 175.671,350.314 175.856,360.179C175.863,360.552 175.848,360.93 175.815,361.214C175.782,361.499 175.735,361.662 175.685,361.662ZM175.488,359.061C175.336,349.946 175.361,340.865 175.545,332.057C175.545,332.057 115.117,332.057 115.117,332.057C115.383,341.094 115.47,350.172 115.395,359.061L175.488,359.061Z"/>
|
||||
</g>
|
||||
<g transform="matrix(3.13548,-1.44294,0.160722,0.349247,-217.31,314.036)">
|
||||
<path d="M174.941,360.361L115.971,360.361C116.331,350.612 116.506,340.628 116.509,330.756L175.008,330.756C174.811,340.66 174.793,350.644 174.941,360.361Z"/>
|
||||
</g>
|
||||
<g transform="matrix(3.13548,-1.44294,0.160722,0.349247,-217.31,314.036)">
|
||||
<path d="M174.941,361.662L115.971,361.662C115.924,361.662 115.881,361.461 115.853,361.123C115.826,360.784 115.819,360.348 115.833,359.952C116.189,350.336 116.361,340.489 116.364,330.752C116.364,330.036 116.429,329.456 116.509,329.456L175.008,329.456C175.051,329.456 175.092,329.626 175.12,329.922C175.147,330.217 175.159,330.606 175.151,330.985C174.956,340.754 174.939,350.601 175.085,360.185C175.09,360.558 175.078,360.934 175.05,361.217C175.023,361.5 174.983,361.662 174.941,361.662ZM174.776,359.061C174.657,350.179 174.673,341.092 174.837,332.057C174.837,332.057 116.652,332.057 116.652,332.057C116.636,341.064 116.479,350.15 116.17,359.061L174.776,359.061Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.9 KiB |
2
images/platforms/black/eurosky.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: derived from https://github.com/eurosky-social/.github/blob/main/profile/logo.png by xje4@chaos.social
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
37
images/platforms/color/atprotocol.svg
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="27"
|
||||
height="27"
|
||||
fill="#3b82f5"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<path
|
||||
d="M13.482 27q-2.934 0-5.4-.972t-4.284-2.754A12.25 12.25 0 0 1 .99 19.116Q0 16.722 0 13.914q0-3.348 1.026-5.94 1.044-2.592 2.88-4.356A12.5 12.5 0 0 1 8.19.918Q10.638 0 13.428 0q3.42 0 5.994 1.062t4.284 2.88A11.7 11.7 0 0 1 26.244 8.1q.828 2.322.756 4.86-.09 3.492-1.458 5.364-1.368 1.854-4.248 1.854a5.84 5.84 0 0 1-2.826-.702 3.7 3.7 0 0 1-1.764-2.07l1.044.054q-.738 1.386-2.016 1.944a6.5 6.5 0 0 1-2.61.558q-1.818 0-3.204-.774a5.7 5.7 0 0 1-2.178-2.214q-.792-1.422-.792-3.294 0-1.926.828-3.33a5.77 5.77 0 0 1 2.232-2.196q1.404-.774 3.168-.774 1.17 0 2.43.486 1.278.486 1.98 1.368l-.738.936V7.884h2.412l-.054 6.462q0 1.386.54 2.088t1.602.702q.936 0 1.44-.522.522-.54.72-1.458a10.7 10.7 0 0 0 .252-2.106q.054-2.79-.828-4.698t-2.394-3.078a9.5 9.5 0 0 0-3.294-1.71q-1.8-.54-3.582-.54-2.52 0-4.482.81-1.962.792-3.312 2.25-1.332 1.44-2.016 3.42-.666 1.962-.63 4.32.072 2.34.846 4.212a9.3 9.3 0 0 0 2.16 3.204 9.4 9.4 0 0 0 3.276 2.034q1.89.702 4.14.702 1.26 0 2.502-.288 1.26-.27 2.304-.774l1.026 2.808q-1.386.648-2.916.954a14.7 14.7 0 0 1-3.078.324m-.144-10.098q1.278 0 2.142-.738t.864-2.502q0-1.602-.774-2.412-.756-.828-2.142-.828-1.638 0-2.448.864t-.81 2.376q0 1.548.828 2.394.846.846 2.34.846" />
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by/4.0/" />
|
||||
<dc:source>https://commons.wikimedia.org/wiki/File:AT_Protocol_Logo.svg</dc:source>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
2
images/platforms/color/atprotocol.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: Derived from https://commons.wikimedia.org/wiki/File:AT_Protocol_Logo.svg
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
82
images/platforms/color/eurosky.svg
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 461 510" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||
<g transform="matrix(1,0,0,1,128.375,27.0069)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:rgb(255,210,35);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:rgb(255,195,35);stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:rgb(255,210,35);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:rgb(255,195,35);stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,67.5926,221.36)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:rgb(255,210,35);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:rgb(255,195,35);stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,374.121,172.829)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:rgb(255,210,35);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:rgb(255,195,35);stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,202.563,-210.015)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:rgb(255,210,35);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:rgb(255,195,35);stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,380.732,-81.8617)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:rgb(255,210,35);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:rgb(255,195,35);stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.759576,-2.35171,0.365844,0.118164,-102.007,679.384)">
|
||||
<path d="M120.752,330.756L173.954,330.756C173.714,340.398 173.702,350.374 173.944,360.361L121.004,360.361C121.159,350.66 121.083,340.686 120.752,330.756Z" style="fill:rgb(20,106,190);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.759576,-2.35171,0.365844,0.118164,-102.007,679.384)">
|
||||
<path d="M120.752,329.456L173.954,329.456C174.013,329.456 174.07,329.623 174.108,329.912C174.147,330.202 174.163,330.586 174.154,330.962C173.917,340.472 173.905,350.31 174.144,360.161C174.153,360.536 174.136,360.919 174.098,361.207C174.06,361.496 174.003,361.662 173.944,361.662L121.004,361.662C120.946,361.662 120.892,361.506 120.853,361.233C120.815,360.959 120.796,360.594 120.802,360.228C120.955,350.659 120.881,340.822 120.554,331.029C120.542,330.645 120.557,330.244 120.595,329.939C120.633,329.633 120.691,329.456 120.752,329.456ZM121,332.057C121.278,341.113 121.347,350.192 121.226,359.061C121.226,359.061 173.71,359.061 173.71,359.061C173.512,349.957 173.521,340.877 173.719,332.057L121,332.057Z" style="fill:rgb(5,75,159);"/>
|
||||
</g>
|
||||
<g transform="matrix(2.99645,1.73569,-0.192701,0.332673,-79.3508,-17.2321)">
|
||||
<path d="M176.303,360.361L114.623,360.361C114.865,350.716 114.943,340.724 114.844,330.756L176.361,330.756C176.173,340.462 176.15,350.453 176.303,360.361Z" style="fill:rgb(20,106,190);"/>
|
||||
</g>
|
||||
<g transform="matrix(2.99645,1.73569,-0.192701,0.332673,-79.3508,-17.2321)">
|
||||
<path d="M176.303,361.662L114.623,361.662C114.579,361.662 114.537,361.482 114.51,361.173C114.482,360.864 114.472,360.46 114.482,360.074C114.721,350.56 114.798,340.703 114.701,330.871C114.697,330.508 114.711,330.147 114.738,329.878C114.765,329.609 114.804,329.456 114.844,329.456L176.361,329.456C176.404,329.456 176.444,329.625 176.472,329.919C176.499,330.213 176.511,330.602 176.504,330.98C176.318,340.554 176.295,350.409 176.446,360.182C176.452,360.555 176.44,360.931 176.412,361.215C176.385,361.499 176.345,361.662 176.303,361.662ZM176.139,359.061C176.015,350.022 176.035,340.931 176.191,332.057C172.647,332.057 115.001,332.057 115.001,332.057C115.076,341.143 115.007,350.236 114.802,359.061L176.139,359.061Z" style="fill:rgb(5,75,159);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.036,0.23923,-0.0865007,0.374596,-16.6075,98.5597)">
|
||||
<path d="M117.078,330.756L172.417,330.756C171.947,340.383 172.006,350.349 172.66,360.361L117.606,360.361C117.983,350.708 117.828,340.743 117.078,330.756Z" style="fill:rgb(20,106,190);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.036,0.23923,-0.0865007,0.374596,-16.6075,98.5597)">
|
||||
<path d="M117.078,329.456L172.417,329.456C172.553,329.456 172.682,329.618 172.771,329.9C172.86,330.183 172.901,330.558 172.883,330.93C172.42,340.425 172.478,350.255 173.123,360.13C173.148,360.51 173.11,360.9 173.021,361.195C172.932,361.491 172.799,361.662 172.66,361.662L117.606,361.662C117.472,361.662 117.345,361.505 117.256,361.23C117.167,360.956 117.124,360.589 117.138,360.222C117.51,350.7 117.358,340.871 116.617,331.021C116.589,330.638 116.624,330.239 116.713,329.935C116.802,329.632 116.936,329.456 117.078,329.456ZM117.651,332.057C118.28,341.159 118.422,350.232 118.126,359.061C118.126,359.061 172.102,359.061 172.102,359.061C171.56,349.938 171.504,340.864 171.883,332.057L117.651,332.057Z" style="fill:rgb(5,75,159);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.891455,-2.76001,0.365844,0.118164,-52.8187,518.104)">
|
||||
<path d="M175.685,360.361L115.21,360.361C115.311,350.635 115.215,340.662 114.9,330.756L175.749,330.756C175.526,340.383 175.497,350.359 175.685,360.361Z" style="fill:rgb(20,106,190);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.891455,-2.76001,0.365844,0.118164,-52.8187,518.104)">
|
||||
<path d="M175.685,361.662L115.21,361.662C115.161,361.662 115.116,361.51 115.083,361.244C115.05,360.978 115.034,360.621 115.038,360.259C115.138,350.666 115.043,340.829 114.733,331.059C114.72,330.672 114.732,330.264 114.765,329.951C114.798,329.638 114.847,329.456 114.9,329.456L175.749,329.456C175.8,329.456 175.848,329.625 175.881,329.919C175.914,330.213 175.927,330.602 175.919,330.98C175.699,340.475 175.671,350.314 175.856,360.179C175.863,360.552 175.848,360.93 175.815,361.214C175.782,361.499 175.735,361.662 175.685,361.662ZM175.488,359.061C175.336,349.946 175.361,340.865 175.545,332.057C175.545,332.057 115.117,332.057 115.117,332.057C115.383,341.094 115.47,350.172 115.395,359.061L175.488,359.061Z" style="fill:rgb(5,75,159);"/>
|
||||
</g>
|
||||
<g transform="matrix(3.13548,-1.44294,0.160722,0.349247,-217.31,314.036)">
|
||||
<path d="M174.941,360.361L115.971,360.361C116.331,350.612 116.506,340.628 116.509,330.756L175.008,330.756C174.811,340.66 174.793,350.644 174.941,360.361Z" style="fill:rgb(20,106,190);"/>
|
||||
</g>
|
||||
<g transform="matrix(3.13548,-1.44294,0.160722,0.349247,-217.31,314.036)">
|
||||
<path d="M174.941,361.662L115.971,361.662C115.924,361.662 115.881,361.461 115.853,361.123C115.826,360.784 115.819,360.348 115.833,359.952C116.189,350.336 116.361,340.489 116.364,330.752C116.364,330.036 116.429,329.456 116.509,329.456L175.008,329.456C175.051,329.456 175.092,329.626 175.12,329.922C175.147,330.217 175.159,330.606 175.151,330.985C174.956,340.754 174.939,350.601 175.085,360.185C175.09,360.558 175.078,360.934 175.05,361.217C175.023,361.5 174.983,361.662 174.941,361.662ZM174.776,359.061C174.657,350.179 174.673,341.092 174.837,332.057C174.837,332.057 116.652,332.057 116.652,332.057C116.636,341.064 116.479,350.15 116.17,359.061L174.776,359.061Z" style="fill:rgb(5,75,159);"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.4 KiB |
2
images/platforms/color/eurosky.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: derived from https://github.com/eurosky-social/.github/blob/main/profile/logo.png by xje4@chaos.social
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
10
images/platforms/color/iceshrimp.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<svg width="367" height="367" viewBox="0 0 367 367" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M169.298 279.39C167.548 277.86 166.519 275.67 166.439 273.35C166.359 271.02 167.249 268.77 168.899 267.13C180.289 255.72 204.238 231.77 204.238 231.77C207.398 228.6 211.689 226.83 216.169 226.83C221.159 226.83 225.348 228.76 228.508 231.92C231.668 235.08 233.448 239.64 233.448 244.11C233.448 248.58 231.668 252.87 228.508 256.04C231.418 253.12 235.799 251.1 240.439 251.1C245.069 251.1 249.348 252.76 252.818 256.24C256.388 259.8 257.718 264.34 257.718 268.38C257.718 272.85 255.938 277.14 252.778 280.3L251.899 281.18C233.779 299.24 195.758 302.8 169.298 279.39Z" fill="url(#paint0_linear_617_810)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M144.75 260.15L135.15 250.54C101.81 217.2 101.81 163.15 135.15 129.81L191.4 73.5595C194.62 70.3395 199.839 70.3395 203.059 73.5595L213.71 84.2094C246.47 116.969 246.47 170.09 213.71 202.85L156.409 260.15C153.189 263.37 147.97 263.37 144.75 260.15ZM172.279 163.17C181.789 172.68 197.209 172.68 206.719 163.17C216.229 153.66 216.229 138.239 206.719 128.729C197.209 119.219 181.789 119.219 172.279 128.729C162.769 138.239 162.769 153.66 172.279 163.17Z" fill="#3B364C"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_617_810" x1="184.288" y1="357.541" x2="112.557" y2="271.225" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#9A92FF"/>
|
||||
<stop offset="1" stop-color="#8372F5"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
2
images/platforms/color/iceshrimp.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: Laura Hausmann. Created by Kilcat https://kilcat.carrd.co/. https://iceshrimp.dev/iceshrimp/branding/src/branch/dev/SVG/Default/Dark/Logo%20Default%20Dark.svg
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
37
images/platforms/white/atprotocol.svg
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="27"
|
||||
height="27"
|
||||
fill="#ffffff"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<path
|
||||
d="M13.482 27q-2.934 0-5.4-.972t-4.284-2.754A12.25 12.25 0 0 1 .99 19.116Q0 16.722 0 13.914q0-3.348 1.026-5.94 1.044-2.592 2.88-4.356A12.5 12.5 0 0 1 8.19.918Q10.638 0 13.428 0q3.42 0 5.994 1.062t4.284 2.88A11.7 11.7 0 0 1 26.244 8.1q.828 2.322.756 4.86-.09 3.492-1.458 5.364-1.368 1.854-4.248 1.854a5.84 5.84 0 0 1-2.826-.702 3.7 3.7 0 0 1-1.764-2.07l1.044.054q-.738 1.386-2.016 1.944a6.5 6.5 0 0 1-2.61.558q-1.818 0-3.204-.774a5.7 5.7 0 0 1-2.178-2.214q-.792-1.422-.792-3.294 0-1.926.828-3.33a5.77 5.77 0 0 1 2.232-2.196q1.404-.774 3.168-.774 1.17 0 2.43.486 1.278.486 1.98 1.368l-.738.936V7.884h2.412l-.054 6.462q0 1.386.54 2.088t1.602.702q.936 0 1.44-.522.522-.54.72-1.458a10.7 10.7 0 0 0 .252-2.106q.054-2.79-.828-4.698t-2.394-3.078a9.5 9.5 0 0 0-3.294-1.71q-1.8-.54-3.582-.54-2.52 0-4.482.81-1.962.792-3.312 2.25-1.332 1.44-2.016 3.42-.666 1.962-.63 4.32.072 2.34.846 4.212a9.3 9.3 0 0 0 2.16 3.204 9.4 9.4 0 0 0 3.276 2.034q1.89.702 4.14.702 1.26 0 2.502-.288 1.26-.27 2.304-.774l1.026 2.808q-1.386.648-2.916.954a14.7 14.7 0 0 1-3.078.324m-.144-10.098q1.278 0 2.142-.738t.864-2.502q0-1.602-.774-2.412-.756-.828-2.142-.828-1.638 0-2.448.864t-.81 2.376q0 1.548.828 2.394.846.846 2.34.846" />
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by/4.0/" />
|
||||
<dc:source>https://commons.wikimedia.org/wiki/File:AT_Protocol_Logo.svg</dc:source>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
2
images/platforms/white/atprotocol.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: Derived from https://commons.wikimedia.org/wiki/File:AT_Protocol_Logo.svg
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
6
images/platforms/white/blacksky.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.0620117 0.348442 87.9941 74.9653">
|
||||
<path d="M41.9565 74.9643L24.0161 74.9653L41.9565 74.9643ZM63.8511 74.9653H45.9097L63.8501 74.9643V57.3286H63.8511V74.9653ZM45.9097 44.5893C45.9099 49.2737 49.7077 53.0707 54.3921 53.0707H63.8501V57.3286H54.3921C49.7077 57.3286 45.9099 61.1257 45.9097 65.81V74.9643H41.9565V65.81C41.9563 61.1258 38.1593 57.3287 33.4751 57.3286H24.0161V53.0707H33.4741C38.1587 53.0707 41.9565 49.2729 41.9565 44.5883V35.1303H45.9097V44.5893ZM63.8511 53.0707H63.8501V35.1303H63.8511V53.0707Z" fill="white"></path>
|
||||
<path d="M52.7272 9.83198C49.4148 13.1445 49.4148 18.5151 52.7272 21.8275L59.4155 28.5158L56.4051 31.5262L49.7169 24.8379C46.4044 21.5254 41.0338 21.5254 37.7213 24.8379L31.2482 31.3111L28.4527 28.5156L34.9259 22.0424C38.2383 18.7299 38.2383 13.3594 34.9259 10.0469L28.2378 3.35883L31.2482 0.348442L37.9365 7.03672C41.2489 10.3492 46.6195 10.3492 49.932 7.03672L56.6203 0.348442L59.4155 3.14371L52.7272 9.83198Z" fill="white"/>
|
||||
<path d="M24.3831 23.2335C23.1706 27.7584 25.8559 32.4095 30.3808 33.6219L39.5172 36.07L38.4154 40.182L29.2793 37.734C24.7544 36.5215 20.1033 39.2068 18.8909 43.7317L16.5215 52.5745L12.7028 51.5513L15.0721 42.7088C16.2846 38.1839 13.5993 33.5328 9.07434 32.3204L-0.0620117 29.8723L1.03987 25.76L10.1762 28.2081C14.7011 29.4206 19.3522 26.7352 20.5647 22.2103L23.0127 13.074L26.8311 14.0971L24.3831 23.2335Z" fill="white"/>
|
||||
<path d="M67.3676 22.0297C68.5801 26.5546 73.2311 29.2399 77.756 28.0275L86.8923 25.5794L87.9941 29.6914L78.8578 32.1394C74.3329 33.3519 71.6476 38.003 72.86 42.5279L75.2294 51.3707L71.411 52.3938L69.0417 43.5513C67.8293 39.0264 63.1782 36.3411 58.6533 37.5535L49.5169 40.0016L48.415 35.8894L57.5514 33.4413C62.0763 32.2288 64.7616 27.5778 63.5492 23.0528L61.1011 13.9165L64.9195 12.8934L67.3676 22.0297Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
2
images/platforms/white/blacksky.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: https://commons.wikimedia.org/wiki/File:Blacksky_Algorithms_Logo.svg
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
82
images/platforms/white/eurosky.svg
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 461 510" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||
<g transform="matrix(1,0,0,1,128.375,27.0069)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:white;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:white;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,67.5926,221.36)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:white;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,374.121,172.829)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:white;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,202.563,-210.015)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:white;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,380.732,-81.8617)">
|
||||
<g transform="matrix(1.53024,0,0,1.53024,-36.1411,-154.896)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.49162,0,0,1.49162,-34.2351,-144.687)">
|
||||
<circle cx="49.353" cy="264.366" r="23.985" style="fill:none;stroke:white;stroke-width:0.67px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.759576,-2.35171,0.365844,0.118164,-102.007,679.384)">
|
||||
<path d="M120.752,330.756L173.954,330.756C173.714,340.398 173.702,350.374 173.944,360.361L121.004,360.361C121.159,350.66 121.083,340.686 120.752,330.756Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.759576,-2.35171,0.365844,0.118164,-102.007,679.384)">
|
||||
<path d="M120.752,329.456L173.954,329.456C174.013,329.456 174.07,329.623 174.108,329.912C174.147,330.202 174.163,330.586 174.154,330.962C173.917,340.472 173.905,350.31 174.144,360.161C174.153,360.536 174.136,360.919 174.098,361.207C174.06,361.496 174.003,361.662 173.944,361.662L121.004,361.662C120.946,361.662 120.892,361.506 120.853,361.233C120.815,360.959 120.796,360.594 120.802,360.228C120.955,350.659 120.881,340.822 120.554,331.029C120.542,330.645 120.557,330.244 120.595,329.939C120.633,329.633 120.691,329.456 120.752,329.456ZM121,332.057C121.278,341.113 121.347,350.192 121.226,359.061C121.226,359.061 173.71,359.061 173.71,359.061C173.512,349.957 173.521,340.877 173.719,332.057L121,332.057Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.99645,1.73569,-0.192701,0.332673,-79.3508,-17.2321)">
|
||||
<path d="M176.303,360.361L114.623,360.361C114.865,350.716 114.943,340.724 114.844,330.756L176.361,330.756C176.173,340.462 176.15,350.453 176.303,360.361Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(2.99645,1.73569,-0.192701,0.332673,-79.3508,-17.2321)">
|
||||
<path d="M176.303,361.662L114.623,361.662C114.579,361.662 114.537,361.482 114.51,361.173C114.482,360.864 114.472,360.46 114.482,360.074C114.721,350.56 114.798,340.703 114.701,330.871C114.697,330.508 114.711,330.147 114.738,329.878C114.765,329.609 114.804,329.456 114.844,329.456L176.361,329.456C176.404,329.456 176.444,329.625 176.472,329.919C176.499,330.213 176.511,330.602 176.504,330.98C176.318,340.554 176.295,350.409 176.446,360.182C176.452,360.555 176.44,360.931 176.412,361.215C176.385,361.499 176.345,361.662 176.303,361.662ZM176.139,359.061C176.015,350.022 176.035,340.931 176.191,332.057C172.647,332.057 115.001,332.057 115.001,332.057C115.076,341.143 115.007,350.236 114.802,359.061L176.139,359.061Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.036,0.23923,-0.0865007,0.374596,-16.6075,98.5597)">
|
||||
<path d="M117.078,330.756L172.417,330.756C171.947,340.383 172.006,350.349 172.66,360.361L117.606,360.361C117.983,350.708 117.828,340.743 117.078,330.756Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.036,0.23923,-0.0865007,0.374596,-16.6075,98.5597)">
|
||||
<path d="M117.078,329.456L172.417,329.456C172.553,329.456 172.682,329.618 172.771,329.9C172.86,330.183 172.901,330.558 172.883,330.93C172.42,340.425 172.478,350.255 173.123,360.13C173.148,360.51 173.11,360.9 173.021,361.195C172.932,361.491 172.799,361.662 172.66,361.662L117.606,361.662C117.472,361.662 117.345,361.505 117.256,361.23C117.167,360.956 117.124,360.589 117.138,360.222C117.51,350.7 117.358,340.871 116.617,331.021C116.589,330.638 116.624,330.239 116.713,329.935C116.802,329.632 116.936,329.456 117.078,329.456ZM117.651,332.057C118.28,341.159 118.422,350.232 118.126,359.061C118.126,359.061 172.102,359.061 172.102,359.061C171.56,349.938 171.504,340.864 171.883,332.057L117.651,332.057Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.891455,-2.76001,0.365844,0.118164,-52.8187,518.104)">
|
||||
<path d="M175.685,360.361L115.21,360.361C115.311,350.635 115.215,340.662 114.9,330.756L175.749,330.756C175.526,340.383 175.497,350.359 175.685,360.361Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.891455,-2.76001,0.365844,0.118164,-52.8187,518.104)">
|
||||
<path d="M175.685,361.662L115.21,361.662C115.161,361.662 115.116,361.51 115.083,361.244C115.05,360.978 115.034,360.621 115.038,360.259C115.138,350.666 115.043,340.829 114.733,331.059C114.72,330.672 114.732,330.264 114.765,329.951C114.798,329.638 114.847,329.456 114.9,329.456L175.749,329.456C175.8,329.456 175.848,329.625 175.881,329.919C175.914,330.213 175.927,330.602 175.919,330.98C175.699,340.475 175.671,350.314 175.856,360.179C175.863,360.552 175.848,360.93 175.815,361.214C175.782,361.499 175.735,361.662 175.685,361.662ZM175.488,359.061C175.336,349.946 175.361,340.865 175.545,332.057C175.545,332.057 115.117,332.057 115.117,332.057C115.383,341.094 115.47,350.172 115.395,359.061L175.488,359.061Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(3.13548,-1.44294,0.160722,0.349247,-217.31,314.036)">
|
||||
<path d="M174.941,360.361L115.971,360.361C116.331,350.612 116.506,340.628 116.509,330.756L175.008,330.756C174.811,340.66 174.793,350.644 174.941,360.361Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(3.13548,-1.44294,0.160722,0.349247,-217.31,314.036)">
|
||||
<path d="M174.941,361.662L115.971,361.662C115.924,361.662 115.881,361.461 115.853,361.123C115.826,360.784 115.819,360.348 115.833,359.952C116.189,350.336 116.361,340.489 116.364,330.752C116.364,330.036 116.429,329.456 116.509,329.456L175.008,329.456C175.051,329.456 175.092,329.626 175.12,329.922C175.147,330.217 175.159,330.606 175.151,330.985C174.956,340.754 174.939,350.601 175.085,360.185C175.09,360.558 175.078,360.934 175.05,361.217C175.023,361.5 174.983,361.662 174.941,361.662ZM174.776,359.061C174.657,350.179 174.673,341.092 174.837,332.057C174.837,332.057 116.652,332.057 116.652,332.057C116.636,341.064 116.479,350.15 116.17,359.061L174.776,359.061Z" style="fill:white;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
2
images/platforms/white/eurosky.svg.license
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SPDX-FileCopyrightText: derived from https://github.com/eurosky-social/.github/blob/main/profile/logo.png by xje4@chaos.social
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
|
|
@ -93,7 +93,7 @@ HELP;
|
|||
'jetstream' => [
|
||||
'pidfile' => '/path/to/jetstream.pid',
|
||||
],
|
||||
TXT
|
||||
TXT,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ HELP;
|
|||
Hook::loadHooks();
|
||||
|
||||
if (!$this->addonHelper->isAddonEnabled('bluesky')) {
|
||||
throw new RuntimeException("Bluesky has to be enabled.\n");
|
||||
throw new RuntimeException("the AT Protocol addon has to be enabled.\n");
|
||||
}
|
||||
|
||||
$pidfile = $this->config->get('jetstream', 'pidfile');
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ use Friendica\Util\Strings;
|
|||
*/
|
||||
class ContactSelector
|
||||
{
|
||||
const SVG_DISABLED = -1;
|
||||
const SVG_COLOR_BLACK = 0;
|
||||
const SVG_BLACK = 1;
|
||||
const SVG_COLOR_WHITE = 2;
|
||||
const SVG_WHITE = 3;
|
||||
public const SVG_DISABLED = -1;
|
||||
public const SVG_COLOR_BLACK = 0;
|
||||
public const SVG_BLACK = 1;
|
||||
public const SVG_COLOR_WHITE = 2;
|
||||
public const SVG_WHITE = 3;
|
||||
|
||||
public static $serverdata = [];
|
||||
public static $server_id = [];
|
||||
|
|
@ -44,7 +44,7 @@ class ContactSelector
|
|||
2 => DI::l10n()->t('Twice daily'),
|
||||
3 => DI::l10n()->t('Daily'),
|
||||
4 => DI::l10n()->t('Weekly'),
|
||||
5 => DI::l10n()->t('Monthly')
|
||||
5 => DI::l10n()->t('Monthly'),
|
||||
];
|
||||
|
||||
foreach ($rep as $k => $v) {
|
||||
|
|
@ -111,7 +111,7 @@ class ContactSelector
|
|||
*
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function networkToName(string $network, string $protocol = '', int $gsid = null): string
|
||||
public static function networkToName(string $network, string $protocol = '', ?int $gsid = null): string
|
||||
{
|
||||
$eventDispatcher = DI::eventDispatcher();
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ class ContactSelector
|
|||
Protocol::ACTIVITYPUB => DI::l10n()->t('ActivityPub'),
|
||||
Protocol::PNUT => DI::l10n()->t('pnut'),
|
||||
Protocol::TUMBLR => DI::l10n()->t('Tumblr'),
|
||||
Protocol::BLUESKY => DI::l10n()->t('Bluesky'),
|
||||
Protocol::ATPROTO => DI::l10n()->t('AT Protocol'),
|
||||
];
|
||||
|
||||
$nets = $eventDispatcher->dispatch(
|
||||
|
|
@ -159,6 +159,11 @@ class ContactSelector
|
|||
if ($platform !== '') {
|
||||
$networkname = $platform;
|
||||
}
|
||||
} elseif ($network === Protocol::ATPROTO && !empty($gsid)) {
|
||||
$gserver = self::getServerForId($gsid);
|
||||
if (isset($gserver['url'])) {
|
||||
$networkname = self::getAtProviderName($gserver['url']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($protocol) && ($protocol != $network) && $network != Protocol::DFRN) {
|
||||
|
|
@ -184,7 +189,7 @@ class ContactSelector
|
|||
* @param integer $uid
|
||||
* @return string
|
||||
*/
|
||||
public static function networkToSVG(string $network, int $gsid = null, string $platform = '', int $uid = 0): string
|
||||
public static function networkToSVG(string $network, ?int $gsid = null, string $platform = '', int $uid = 0): string
|
||||
{
|
||||
$platform_icon_style = $uid ? (DI::pConfig()->get($uid, 'accessibility', 'platform_icon_style') ?? self::SVG_COLOR_BLACK) : self::SVG_COLOR_BLACK;
|
||||
|
||||
|
|
@ -194,7 +199,7 @@ class ContactSelector
|
|||
|
||||
$nets = [
|
||||
Protocol::ACTIVITYPUB => 'activitypub', // https://commons.wikimedia.org/wiki/File:ActivityPub-logo-symbol.svg
|
||||
Protocol::BLUESKY => 'bluesky', // https://commons.wikimedia.org/wiki/File:Bluesky_Logo.svg
|
||||
Protocol::ATPROTO => 'atprotocol', // https://freesvg.org/at-sign-symbol
|
||||
Protocol::DFRN => 'friendica',
|
||||
Protocol::DIASPORA => 'diaspora', // https://www.svgrepo.com/svg/362315/diaspora
|
||||
Protocol::DIASPORA2 => 'diaspora', // https://www.svgrepo.com/svg/362315/diaspora
|
||||
|
|
@ -218,12 +223,15 @@ class ContactSelector
|
|||
if (in_array($network, Protocol::FEDERATED) && !empty($gsid)) {
|
||||
$gserver = self::getServerForId($gsid);
|
||||
$platform = $gserver['platform'];
|
||||
} elseif ($network === Protocol::ATPROTO && !empty($gsid)) {
|
||||
$gserver = self::getServerForId($gsid);
|
||||
$platform = self::getAtProtoProvider($gserver['url']);
|
||||
}
|
||||
|
||||
$svg = ['aardwolf', 'activitypods', 'activitypub', 'akkoma', 'anfora', 'awakari', 'azorius',
|
||||
'bluesky', 'bonfire', 'bookwyrm', 'bridgy_fed', 'brighteon_social', 'brutalinks', 'calckey',
|
||||
$svg = ['aardwolf', 'activitypods', 'activitypub', 'akkoma', 'anfora', 'atprotocol', 'awakari', 'azorius',
|
||||
'blacksky', 'bluesky', 'bonfire', 'bookwyrm', 'bridgy_fed', 'brighteon_social', 'brutalinks', 'calckey',
|
||||
'castopod', 'catodon', 'chatter_net', 'chuckya', 'clubsall', 'communecter', 'decodon',
|
||||
'diaspora', 'discourse', 'dolphin', 'drupal', 'email', 'emissary', 'epicyon', 'f2ap',
|
||||
'diaspora', 'discourse', 'dolphin', 'drupal', 'email', 'emissary', 'epicyon', 'eurosky', 'f2ap',
|
||||
'fedibird', 'fedify', 'firefish', 'flipboard', 'flohmarkt', 'forgefriends', 'forgejo',
|
||||
'forte', 'foundkey', 'friendica', 'funkwhale', 'gancio', 'gath.io', 'ghost', 'gitlab',
|
||||
'glitch-soc', 'glitchsoc', 'gnu_social', 'gnusocial', 'goblin', 'go-fed', 'gotosocial',
|
||||
|
|
@ -238,8 +246,8 @@ class ContactSelector
|
|||
'wildebeest', 'wordpress', 'write.as', 'writefreely', 'wxwclub', 'xwiki', 'zap'];
|
||||
|
||||
if (in_array($platform_icon_style, [self::SVG_WHITE, self::SVG_COLOR_WHITE])) {
|
||||
$svg = ['activitypub', 'akkoma', 'andstatus', 'bluesky', 'bonfire', 'bookwyrm', 'bridgy_fed',
|
||||
'calckey', 'castopod', 'diaspora', 'discourse', 'dolphin', 'drupal', 'email', 'firefish',
|
||||
$svg = ['activitypub', 'akkoma', 'andstatus', 'atprotocol', 'blacksky', 'bluesky', 'bonfire', 'bookwyrm', 'bridgy_fed',
|
||||
'calckey', 'castopod', 'diaspora', 'discourse', 'dolphin', 'drupal', 'email', 'eurosky', 'firefish',
|
||||
'flipboard', 'flohmarkt', 'forgejo', 'friendica', 'funkwhale', 'ghost', 'gitlab',
|
||||
'glitch-soc', 'gnusocial', 'gotosocial', 'guppe', 'hollo', 'hubzilla', 'iceshrimp', 'kbin',
|
||||
'lemmy', 'loforo', 'loops', 'mastodon', 'mbin', 'microblog', 'minds', 'misskey', 'mobilizon',
|
||||
|
|
@ -273,8 +281,8 @@ class ContactSelector
|
|||
return '';
|
||||
}
|
||||
|
||||
$color = ['aardwolf', 'activitypods', 'activitypub', 'akkoma', 'bluesky', 'chuckya', 'decodon',
|
||||
'discourse', 'fedify', 'firefish', 'flipboard', 'friendica', 'gitlab', 'gnusocial', 'kookie',
|
||||
$color = ['aardwolf', 'activitypods', 'activitypub', 'akkoma', 'atprotocol', 'bluesky', 'chuckya', 'decodon',
|
||||
'discourse', 'eurosky', 'fedify', 'firefish', 'flipboard', 'friendica', 'gitlab', 'gnusocial', 'iceshrimp', 'kookie',
|
||||
'loops', 'mastodon', 'mbin', 'misskey', 'neodb', 'newsmast', 'nodebb', 'peertube', 'pixelfed',
|
||||
'pleroma', 'rss', 'sharky', 'tumblr', 'vervis', 'vocata', 'wordpress'];
|
||||
|
||||
|
|
@ -286,4 +294,35 @@ class ContactSelector
|
|||
return 'images/platforms/black/' . $network_svg . '.svg';
|
||||
}
|
||||
}
|
||||
|
||||
private static function getAtProtoProvider(string $pds): string
|
||||
{
|
||||
$host = parse_url($pds, PHP_URL_HOST);
|
||||
if (str_ends_with($host, '.host.bsky.network')) {
|
||||
return 'bluesky';
|
||||
} elseif ($host === 'fed.brid.gy') {
|
||||
return 'bridgy_fed';
|
||||
} elseif ($host === 'eurosky.social') {
|
||||
return 'eurosky';
|
||||
} elseif ($host === 'blacksky.app') {
|
||||
return 'blacksky';
|
||||
}
|
||||
return 'atprotocol';
|
||||
}
|
||||
|
||||
private static function getAtProviderName(string $pds): string
|
||||
{
|
||||
switch (self::getAtProtoProvider($pds)) {
|
||||
case 'bluesky':
|
||||
return 'Bluesky';
|
||||
case 'bridgy_fed':
|
||||
return 'Bridgy Fed';
|
||||
case 'eurosky':
|
||||
return 'Eurosky';
|
||||
case 'blacksky':
|
||||
return 'Blacksky';
|
||||
default:
|
||||
return parse_url($pds, PHP_URL_HOST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,12 +72,13 @@ class GroupManager
|
|||
|
||||
while ($contact = DBA::fetch($contacts)) {
|
||||
$groupList[] = [
|
||||
'url' => $contact['url'],
|
||||
'alias' => $contact['alias'],
|
||||
'name' => $contact['name'],
|
||||
'id' => $contact['id'],
|
||||
'micro' => $contact['micro'],
|
||||
'thumb' => $contact['thumb'],
|
||||
'url' => $contact['url'],
|
||||
'alias' => $contact['alias'],
|
||||
'name' => $contact['name'],
|
||||
'id' => $contact['id'],
|
||||
'micro' => $contact['micro'],
|
||||
'thumb' => $contact['thumb'],
|
||||
'network' => $contact['network'],
|
||||
];
|
||||
}
|
||||
DBA::close($contacts);
|
||||
|
|
@ -208,7 +209,7 @@ class GroupManager
|
|||
Protocol::DFRN,
|
||||
Protocol::ACTIVITYPUB,
|
||||
Contact::TYPE_COMMUNITY,
|
||||
DI::userSession()->getLocalUserId()
|
||||
DI::userSession()->getLocalUserId(),
|
||||
);
|
||||
|
||||
return DBA::toArray($stmtContacts);
|
||||
|
|
|
|||
|
|
@ -711,7 +711,7 @@ class Item
|
|||
|
||||
// If it is a reshared post then reformat it to avoid display problems with two share elements
|
||||
if (!empty($shared)) {
|
||||
if (($item['network'] != Protocol::BLUESKY) && !empty($shared['guid']) && ($encapsulated_share = $this->createSharedPostByGuid($shared['guid'], true))) {
|
||||
if (($item['network'] != Protocol::ATPROTO) && !empty($shared['guid']) && ($encapsulated_share = $this->createSharedPostByGuid($shared['guid'], true))) {
|
||||
if (!empty(BBCode::fetchShareAttributes($item['body']))) {
|
||||
$item['body'] = preg_replace("/\[share.*?\](.*)\[\/share\]/ism", $encapsulated_share, $item['body']);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -70,11 +70,18 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow
|
|||
$row['embed-width'],
|
||||
$row['embed-height'],
|
||||
$row['page-type'],
|
||||
$row['schematypes'] ? json_decode($row['schematypes'], true) : null
|
||||
$row['schematypes'] ? json_decode($row['schematypes'], true) : null,
|
||||
);
|
||||
}
|
||||
|
||||
public function createFromBlueskyImageEmbed(int $uriId, stdClass $image): PostMediaEntity
|
||||
/**
|
||||
* Create a PostMedia entity from an image element
|
||||
*
|
||||
* @param integer $uriId
|
||||
* @param stdClass $image
|
||||
* @return PostMediaEntity
|
||||
*/
|
||||
public function createFromATProtocolImageEmbed(int $uriId, stdClass $image): PostMediaEntity
|
||||
{
|
||||
return new PostMediaEntity(
|
||||
$uriId,
|
||||
|
|
@ -92,8 +99,14 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
public function createFromBlueskyExternalEmbed(int $uriId, stdClass $external): PostMediaEntity
|
||||
/**
|
||||
* Create a PostMedia entity from an external embed element
|
||||
*
|
||||
* @param integer $uriId
|
||||
* @param stdClass $external
|
||||
* @return PostMediaEntity
|
||||
*/
|
||||
public function createFromATProtocolExternalEmbed(int $uriId, stdClass $external): PostMediaEntity
|
||||
{
|
||||
return new PostMediaEntity(
|
||||
$uriId,
|
||||
|
|
@ -108,10 +121,18 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow
|
|||
null,
|
||||
null,
|
||||
$external->description,
|
||||
$external->title
|
||||
$external->title,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PostMedia entity from an attachment array
|
||||
*
|
||||
* @param array $attachment
|
||||
* @param integer $uriId
|
||||
* @param integer $id
|
||||
* @return PostMediaEntity
|
||||
*/
|
||||
public function createFromAttachment(array $attachment, int $uriId = 0, int $id = 0)
|
||||
{
|
||||
$row = [
|
||||
|
|
@ -163,6 +184,14 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow
|
|||
return $this->createFromTableRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PostMedia entity from parsed URL data
|
||||
*
|
||||
* @param array $data
|
||||
* @param integer $uriId
|
||||
* @param integer $id
|
||||
* @return PostMediaEntity
|
||||
*/
|
||||
public function createFromParseUrl(array $data, int $uriId = 0, int $id = 0)
|
||||
{
|
||||
$row = [
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ class BBCode
|
|||
public const TWITTER = 8;
|
||||
public const BACKLINK = 8;
|
||||
public const ACTIVITYPUB = 9;
|
||||
public const BLUESKY = 10;
|
||||
public const ATPROTOCOL = 10;
|
||||
/** @deprecated use @see ATPROTOCOL instead */
|
||||
public const BLUESKY = 10; // @deprecated
|
||||
|
||||
public const SHARED_ANCHOR = '<hr class="shared-anchor">';
|
||||
public const TOP_ANCHOR = '<br class="top-anchor">';
|
||||
|
|
@ -1999,7 +2001,7 @@ class BBCode
|
|||
$text,
|
||||
);
|
||||
|
||||
if (in_array($simple_html, [self::TWITTER, self::BLUESKY])) {
|
||||
if (in_array($simple_html, [self::TWITTER, self::ATPROTOCOL])) {
|
||||
$text = preg_replace_callback("/([^#@!])\[url\=([^\]]*)\](.*?)\[\/url\]/ism", [self::class, 'expandLinksCallback'], $text);
|
||||
//$text = preg_replace("/[^#@!]\[url\=([^\]]*)\](.*?)\[\/url\]/ism", ' $2 [url]$1[/url]', $text);
|
||||
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", ' $2 [url]$1[/url]', $text);
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ class Plaintext
|
|||
$abstract = BBCode::getAbstract($item['body'], Protocol::TWITTER);
|
||||
break;
|
||||
|
||||
case BBCode::BLUESKY:
|
||||
$abstract = BBCode::getAbstract($item['body'], Protocol::BLUESKY);
|
||||
case BBCode::ATPROTOCOL:
|
||||
$abstract = BBCode::getAbstract($item['body'], Protocol::ATPROTO);
|
||||
break;
|
||||
|
||||
default: // We don't know the exact target.
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class VCard
|
|||
$contact_url = Contact::getProfileLink($contact);
|
||||
|
||||
if ($contact['network'] != '') {
|
||||
$network_link = Strings::formatNetworkName($contact['network'], $contact_url);
|
||||
$network_link = Strings::formatNetworkName($contact['network'], $contact_url, $contact['gsid']);
|
||||
$network_svg = ContactSelector::networkToSVG($contact['network'], $contact['gsid'], '', DI::userSession()->getLocalUserId());
|
||||
} else {
|
||||
$network_link = '';
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@ class Protocol
|
|||
public const SUPPORT_PRIVATE = [self::DFRN, self::DIASPORA, self::MAIL, self::ACTIVITYPUB, self::PUMPIO];
|
||||
|
||||
// Supported through a connector
|
||||
public const BLUESKY = 'bsky'; // Bluesky
|
||||
/** @deprecated use @see ATPROTO instead */
|
||||
public const BLUESKY = 'bsky'; // @deprecated name for the AT Protocol
|
||||
public const ATPROTO = 'bsky'; // AT Protocol, short name "atproto" (Formerly known as Bluesky)
|
||||
public const DIASPORA2 = 'dspc'; // Diaspora connector
|
||||
public const DISCOURSE = 'dscs'; // Discourse
|
||||
public const PNUT = 'pnut'; // pnut.io
|
||||
|
|
@ -334,7 +336,7 @@ class Protocol
|
|||
return false;
|
||||
}
|
||||
|
||||
if (in_array($protocol, array_merge(self::NATIVE_SUPPORT, [self::ZOT, self::BLUESKY, self::PHANTOM]))) {
|
||||
if (in_array($protocol, array_merge(self::NATIVE_SUPPORT, [self::ZOT, self::ATPROTO, self::PHANTOM]))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ use Friendica\Network\Probe;
|
|||
use Friendica\Object\Image;
|
||||
use Friendica\Protocol\Activity;
|
||||
use Friendica\Protocol\ActivityPub;
|
||||
use Friendica\Protocol\ATProtocol;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\HTTPSignature;
|
||||
use Friendica\Util\Images;
|
||||
|
|
@ -3592,13 +3593,23 @@ class Contact
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the link to the profile
|
||||
* Return the profile link for a given contact array
|
||||
*
|
||||
* @param array $contact
|
||||
* @return string
|
||||
* Returns the alias if it is set, otherwise returns the URL
|
||||
*
|
||||
* @param array $contact Contact record
|
||||
* @return string The profile link (alias or url)
|
||||
*/
|
||||
public static function getProfileLink(array $contact): string
|
||||
{
|
||||
if ($contact['network'] === Protocol::ATPROTO) {
|
||||
$web = DI::atProtocol()->getWebForUser(DI::userSession()->getLocalUserId());
|
||||
if ($web) {
|
||||
return str_replace(ATProtocol::WEB, rtrim($web, '/'), $contact['alias']);
|
||||
} else {
|
||||
return $contact['alias'];
|
||||
}
|
||||
}
|
||||
if (!empty($contact['alias']) && Network::isValidHttpUrl($contact['alias']) && (($contact['network'] ?? '') != Protocol::DFRN)) {
|
||||
return $contact['alias'];
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class GServer
|
|||
public const DETECT_V1_CONFIG = 18;
|
||||
public const DETECT_SYSTEM_ACTOR = 20; // Mistpark, Osada, Roadhouse, Zap
|
||||
public const DETECT_THREADS = 21;
|
||||
public const DETECT_ATPROTO_PDS = 22;
|
||||
|
||||
// Standardized endpoints
|
||||
public const DETECT_STATISTICS_JSON = 100;
|
||||
|
|
@ -714,6 +715,10 @@ class GServer
|
|||
$serverdata['platform'] = 'threads';
|
||||
}
|
||||
|
||||
if ($serverdata['network'] === Protocol::PHANTOM) {
|
||||
$serverdata = self::detectATProto($url, $serverdata);
|
||||
}
|
||||
|
||||
// All following checks are done for systems that always have got a "host-meta" endpoint.
|
||||
// With this check we don't have to waste time and resources for dead systems.
|
||||
// Also this hopefully prevents us from receiving abuse messages.
|
||||
|
|
@ -1643,6 +1648,24 @@ class GServer
|
|||
return $serverdata;
|
||||
}
|
||||
|
||||
private static function detectATProto(string $url, array $serverdata): array
|
||||
{
|
||||
$data = DI::atProtocol()->get($url . '/xrpc/com.atproto.server.describeServer');
|
||||
if (!isset($data->did)) {
|
||||
return $serverdata;
|
||||
}
|
||||
|
||||
$serverdata['detection-method'] = self::DETECT_ATPROTO_PDS;
|
||||
$serverdata['network'] = Protocol::ATPROTO;
|
||||
$serverdata['platform'] = 'atproto';
|
||||
|
||||
if (isset($data->inviteCodeRequired)) {
|
||||
$serverdata['register_policy'] = Register::APPROVE;
|
||||
}
|
||||
|
||||
return $serverdata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches server data via an ActivityPub account with url of that server
|
||||
*
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ use Friendica\Network\HTTPException\ServiceUnavailableException;
|
|||
use Friendica\Protocol\Activity;
|
||||
use Friendica\Protocol\ActivityPub;
|
||||
use Friendica\Protocol\ActivityPub\Processor;
|
||||
use Friendica\Protocol\ATProtocol;
|
||||
use Friendica\Protocol\Delivery;
|
||||
use Friendica\Protocol\Diaspora;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
|
@ -1539,7 +1540,7 @@ class Item
|
|||
}
|
||||
}
|
||||
|
||||
if (($source_uid == 0) && (($item['private'] == self::PRIVATE) || !in_array($item['network'], array_merge(Protocol::FEDERATED, [Protocol::BLUESKY])))) {
|
||||
if (($source_uid == 0) && (($item['private'] == self::PRIVATE) || !in_array($item['network'], array_merge(Protocol::FEDERATED, [Protocol::ATPROTO])))) {
|
||||
DI::logger()->notice('Item is private or not from a federated network. It will not be stored for the user.', ['uri-id' => $uri_id, 'uid' => $uid, 'private' => $item['private'], 'network' => $item['network']]);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3713,7 +3714,14 @@ class Item
|
|||
*/
|
||||
public static function getPlink(array $item)
|
||||
{
|
||||
if (!empty($item['plink']) && Network::isValidHttpUrl($item['plink'])) {
|
||||
if ($item['network'] === Protocol::ATPROTO) {
|
||||
$web = DI::atProtocol()->getWebForUser(DI::userSession()->getLocalUserId());
|
||||
if ($web) {
|
||||
$plink = str_replace(ATProtocol::WEB, rtrim($web, '/'), $item['plink']);
|
||||
} else {
|
||||
$plink = $item['plink'];
|
||||
}
|
||||
} elseif (!empty($item['plink']) && Network::isValidHttpUrl($item['plink'])) {
|
||||
$plink = $item['plink'];
|
||||
} elseif (!empty($item['uri']) && Network::isValidHttpUrl($item['uri']) && !DI::baseUrl()->isLocalUrl($item['uri'])) {
|
||||
$plink = $item['uri'];
|
||||
|
|
|
|||
|
|
@ -103,10 +103,15 @@ class Nodeinfo
|
|||
'outbound' => [],
|
||||
];
|
||||
|
||||
if ($addonHelper->isAddonEnabled('bluesky')) {
|
||||
$services['inbound'][] = 'bluesky';
|
||||
$services['outbound'][] = 'bluesky';
|
||||
}
|
||||
// @see discussion at https://github.com/jhass/nodeinfo/issues/96#issuecomment-3240296214
|
||||
// Currently disabled, since this currently isn't covered by the Nodeinfo specification
|
||||
//if ($addonHelper->isAddonEnabled('bluesky')) {
|
||||
// $services['inbound'][] = 'atproto-pds';
|
||||
// $services['outbound'][] = 'atproto-pds';
|
||||
// if (!is_null(DI::config()->get('jetstream', 'pidfile'))) {
|
||||
// $services['inbound'][] = 'atproto-jetstream';
|
||||
// }
|
||||
//}
|
||||
if ($addonHelper->isAddonEnabled('dwpost')) {
|
||||
$services['outbound'][] = 'dreamwidth';
|
||||
}
|
||||
|
|
@ -131,6 +136,8 @@ class Nodeinfo
|
|||
$services['outbound'][] = 'smtp';
|
||||
|
||||
if ($addonHelper->isAddonEnabled('tumblr')) {
|
||||
// Currently disabled, since this currently isn't covered by the Nodeinfo specification
|
||||
// $services['inbound'][] = 'tumblr';
|
||||
$services['outbound'][] = 'tumblr';
|
||||
}
|
||||
if ($addonHelper->isAddonEnabled('twitter')) {
|
||||
|
|
|
|||
|
|
@ -24,19 +24,20 @@ use Friendica\Util\DateTimeFormat;
|
|||
|
||||
class Engagement
|
||||
{
|
||||
const KEYWORDS = ['source', 'server', 'from', 'to', 'group', 'application', 'tag', 'network', 'platform', 'visibility', 'language', 'media'];
|
||||
const SHORTCUTS = ['lang' => 'language', 'net' => 'network', 'relay' => 'application'];
|
||||
const ALTERNATIVES = ['source:news' => 'source:service', 'source:relay' => 'source:application',
|
||||
'media:picture' => 'media:image', 'media:photo' => 'media:image',
|
||||
'network:activitypub' => 'network:apub', 'network:friendica' => 'network:dfrn',
|
||||
'network:diaspora' => 'network:dspr', 'network:discourse' => 'network:dscs',
|
||||
'network:tumblr' => 'network:tmbl', 'network:bluesky' => 'network:bsky'];
|
||||
const MEDIA_NONE = 0;
|
||||
const MEDIA_IMAGE = 1;
|
||||
const MEDIA_VIDEO = 2;
|
||||
const MEDIA_AUDIO = 4;
|
||||
const MEDIA_CARD = 8;
|
||||
const MEDIA_POST = 16;
|
||||
public const KEYWORDS = ['source', 'server', 'from', 'to', 'group', 'application', 'tag', 'network', 'platform', 'visibility', 'language', 'media'];
|
||||
public const SHORTCUTS = ['lang' => 'language', 'net' => 'network', 'relay' => 'application'];
|
||||
public const ALTERNATIVES = ['source:news' => 'source:service', 'source:relay' => 'source:application',
|
||||
'media:picture' => 'media:image', 'media:photo' => 'media:image',
|
||||
'network:activitypub' => 'network:apub', 'network:friendica' => 'network:dfrn',
|
||||
'network:diaspora' => 'network:dspr', 'network:discourse' => 'network:dscs',
|
||||
'network:tumblr' => 'network:tmbl', 'network:bluesky' => 'network:bsky',
|
||||
'network:atprotocol' => 'network:bsky', 'network:atproto' => 'network:bsky'];
|
||||
public const MEDIA_NONE = 0;
|
||||
public const MEDIA_IMAGE = 1;
|
||||
public const MEDIA_VIDEO = 2;
|
||||
public const MEDIA_AUDIO = 4;
|
||||
public const MEDIA_CARD = 8;
|
||||
public const MEDIA_POST = 16;
|
||||
|
||||
/**
|
||||
* Store engagement data from an item array
|
||||
|
|
@ -56,7 +57,7 @@ class Engagement
|
|||
'contact-contact-type', 'network', 'title', 'content-warning', 'body', 'language',
|
||||
'author-id', 'author-contact-type', 'author-nick', 'author-addr', 'author-gsid',
|
||||
'owner-id', 'owner-contact-type', 'owner-nick', 'owner-addr', 'owner-gsid'],
|
||||
['uri-id' => $item['parent-uri-id']]
|
||||
['uri-id' => $item['parent-uri-id']],
|
||||
);
|
||||
|
||||
if ($parent['created'] < self::getCreationDateLimit(false)) {
|
||||
|
|
@ -112,7 +113,7 @@ class Engagement
|
|||
'activities' => DBA::count('post', [
|
||||
"`parent-uri-id` = ? AND `gravity` = ? AND NOT `vid` IN (?, ?, ?)",
|
||||
$item['parent-uri-id'], Item::GRAVITY_ACTIVITY,
|
||||
Verb::getID(Activity::FOLLOW), Verb::getID(Activity::VIEW), Verb::getID(Activity::READ)
|
||||
Verb::getID(Activity::FOLLOW), Verb::getID(Activity::VIEW), Verb::getID(Activity::READ),
|
||||
]),
|
||||
];
|
||||
if (!$store && ($engagement['comments'] == 0) && ($engagement['activities'] == 0)) {
|
||||
|
|
@ -319,7 +320,7 @@ class Engagement
|
|||
{
|
||||
$result = Post::selectPosts(
|
||||
['author-addr', 'author-nick', 'author-contact-type'],
|
||||
['thr-parent-id' => $uri_id, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::ANNOUNCE, 'author-contact-type' => [Contact::TYPE_RELAY, Contact::TYPE_COMMUNITY]]
|
||||
['thr-parent-id' => $uri_id, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::ANNOUNCE, 'author-contact-type' => [Contact::TYPE_RELAY, Contact::TYPE_COMMUNITY]],
|
||||
);
|
||||
while ($reshare = Post::fetch($result)) {
|
||||
$prefix = '';
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
|||
use Friendica\Network\HTTPClient\Client\HttpClientRequest;
|
||||
use Friendica\Object\Image;
|
||||
use Friendica\Protocol\ActivityPub;
|
||||
use Friendica\Protocol\ATProtocol;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Images;
|
||||
use Friendica\Util\Network;
|
||||
|
|
@ -309,10 +308,6 @@ class Media
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Strings::compareLink($baseurl, ATProtocol::WEB)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return DBA::exists('gserver', ['nurl' => Strings::normaliseLink($baseurl), 'network' => Protocol::FEDERATED]);
|
||||
} catch (\Throwable $e) {
|
||||
DI::logger()->notice('Invalid URL provided', ['url' => $url, 'exception' => $e, 'callstack' => System::callstack(10)]);
|
||||
|
|
@ -474,6 +469,7 @@ class Media
|
|||
private static function addPage(array $media): array
|
||||
{
|
||||
$data = ParseUrl::getSiteinfoCached($media['url'], $media['mimetype'] ?? '');
|
||||
// @todo Add detected AT Protocol activities and accounts here
|
||||
if (empty($data['images'][0]['src']) && empty($data['text']) && empty($data['title'])) {
|
||||
if (!empty($media['preview'])) {
|
||||
$media = self::addPreviewData($media);
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ class Reblog extends BaseApi
|
|||
|
||||
if ($item['network'] == Protocol::DIASPORA) {
|
||||
Diaspora::performReshare($this->parameters['id'], $uid);
|
||||
} elseif (!in_array($item['network'], [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::BLUESKY, Protocol::TUMBLR, Protocol::TWITTER])) {
|
||||
} elseif (!in_array($item['network'], [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::ATPROTO, Protocol::TUMBLR, Protocol::TWITTER])) {
|
||||
$this->logAndJsonError(
|
||||
422,
|
||||
$this->errorFactory->UnprocessableEntity($this->t("Posts from %s can't be shared", ContactSelector::networkToName($item['network'])))
|
||||
$this->errorFactory->UnprocessableEntity($this->t("Posts from %s can't be shared", ContactSelector::networkToName($item['network']))),
|
||||
);
|
||||
} else {
|
||||
Item::performActivity($item['id'], 'announce', $uid);
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ class Unreblog extends BaseApi
|
|||
if (!Item::markForDeletionById($item['id'])) {
|
||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||
}
|
||||
} elseif (!in_array($item['network'], [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::BLUESKY, Protocol::TUMBLR, Protocol::TWITTER])) {
|
||||
} elseif (!in_array($item['network'], [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::ATPROTO, Protocol::TUMBLR, Protocol::TWITTER])) {
|
||||
$this->logAndJsonError(
|
||||
422,
|
||||
$this->errorFactory->UnprocessableEntity($this->t("Posts from %s can't be unshared", ContactSelector::networkToName($item['network'])))
|
||||
$this->errorFactory->UnprocessableEntity($this->t("Posts from %s can't be unshared", ContactSelector::networkToName($item['network']))),
|
||||
);
|
||||
} else {
|
||||
Item::performActivity($item['id'], 'unannounce', $uid);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class Retweet extends BaseApi
|
|||
$item = Post::selectFirst($fields, ['uri-id' => $id, 'uid' => [0, $uid], 'private' => [Item::PUBLIC, Item::UNLISTED]], ['order' => ['uid' => true]]);
|
||||
|
||||
if (DBA::isResult($item) && !empty($item['body'])) {
|
||||
if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::BLUESKY, Protocol::TUMBLR, Protocol::TWITTER])) {
|
||||
if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::ATPROTO, Protocol::TUMBLR, Protocol::TWITTER])) {
|
||||
if (!Item::performActivity($id, 'announce', $uid)) {
|
||||
throw new InternalServerErrorException();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,8 +159,8 @@ class Follow extends BaseModule
|
|||
|
||||
'$action' => $requestUrl,
|
||||
'$name' => $contact['name'],
|
||||
'$url' => $contact['alias'] ?: $contact['url'],
|
||||
'$zrl' => OpenWebAuth::getZrlUrl($contact['alias'] ?: $contact['url']),
|
||||
'$url' => Contact::getProfileLink($contact),
|
||||
'$zrl' => OpenWebAuth::getZrlUrl(Contact::getProfileLink($contact)),
|
||||
'$myaddr' => $myaddr,
|
||||
'$keywords' => $contact['keywords'],
|
||||
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ class Profile extends BaseModule
|
|||
'$sparkle' => $sparkle,
|
||||
'$url' => $url,
|
||||
'$profileurllabel' => $this->t('Profile URL'),
|
||||
'$profileurl' => $contact['alias'] ?: $contact['url'],
|
||||
'$profileurl' => ContactModel::getProfileLink($contact),
|
||||
'$account_type' => ContactModel::getAccountType($contact['contact-type']),
|
||||
'$location' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['location']),
|
||||
'$location_label' => $this->t('Location:'),
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ class Unfollow extends \Friendica\BaseModule
|
|||
'$invite_desc' => '',
|
||||
'$submit' => $this->t('Submit Request'),
|
||||
'$cancel' => $this->t('Cancel'),
|
||||
'$url' => $contact['url'],
|
||||
'$url' => Contact::getProfileLink($contact),
|
||||
'$zrl' => Contact::magicLinkByContact($contact),
|
||||
'$url_label' => $this->t('Profile URL'),
|
||||
'$myaddr' => $self['url'],
|
||||
|
|
|
|||
|
|
@ -58,12 +58,12 @@ class Statistics extends BaseModule
|
|||
|
||||
/// @todo mark the "service" addons and load them dynamically here
|
||||
$services = [
|
||||
'appnet' => $this->addonHelper->isAddonEnabled('appnet'),
|
||||
'bluesky' => $this->addonHelper->isAddonEnabled('bluesky'),
|
||||
'atprotocol' => $this->addonHelper->isAddonEnabled('bluesky'),
|
||||
'dreamwidth' => $this->addonHelper->isAddonEnabled('dreamwidth'),
|
||||
'gnusocial' => $this->addonHelper->isAddonEnabled('gnusocial'),
|
||||
'libertree' => $this->addonHelper->isAddonEnabled('libertree'),
|
||||
'livejournal' => $this->addonHelper->isAddonEnabled('livejournal'),
|
||||
'pnut' => $this->addonHelper->isAddonEnabled('pnut'),
|
||||
'pumpio' => $this->addonHelper->isAddonEnabled('pumpio'),
|
||||
'twitter' => $this->addonHelper->isAddonEnabled('twitter'),
|
||||
'tumblr' => $this->addonHelper->isAddonEnabled('tumblr'),
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ class Stats extends BaseModule
|
|||
$statistics = [
|
||||
'cron' => [
|
||||
'lastExecution' => [
|
||||
'datetime' => date(DateTimeFormat::JSON, (int)$this->keyValue->get('last_cron')),
|
||||
'timestamp' => (int)$this->keyValue->get('last_cron'),
|
||||
'datetime' => date(DateTimeFormat::JSON, (int) $this->keyValue->get('last_cron')),
|
||||
'timestamp' => (int) $this->keyValue->get('last_cron'),
|
||||
],
|
||||
],
|
||||
'worker' => [
|
||||
|
|
@ -150,7 +150,7 @@ class Stats extends BaseModule
|
|||
Protocol::OSTATUS => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::OSTATUS) ?? 0),
|
||||
Protocol::FEED => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::FEED) ?? 0),
|
||||
Protocol::MAIL => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::MAIL) ?? 0),
|
||||
]
|
||||
],
|
||||
],
|
||||
'reports' => [
|
||||
'newest' => [
|
||||
|
|
@ -181,8 +181,8 @@ class Stats extends BaseModule
|
|||
];
|
||||
|
||||
if ($this->addonHelper->isAddonEnabled('bluesky')) {
|
||||
$statistics['packets']['inbound'][Protocol::BLUESKY] = intval($this->keyValue->get('stats_packets_inbound_' . Protocol::BLUESKY) ?? 0);
|
||||
$statistics['packets']['outbound'][Protocol::BLUESKY] = intval($this->keyValue->get('stats_packets_outbound_' . Protocol::BLUESKY) ?? 0);
|
||||
$statistics['packets']['inbound'][Protocol::ATPROTO] = intval($this->keyValue->get('stats_packets_inbound_' . Protocol::ATPROTO) ?? 0);
|
||||
$statistics['packets']['outbound'][Protocol::ATPROTO] = intval($this->keyValue->get('stats_packets_outbound_' . Protocol::ATPROTO) ?? 0);
|
||||
}
|
||||
if ($this->addonHelper->isAddonEnabled('tumblr')) {
|
||||
$statistics['packets']['inbound'][Protocol::TUMBLR] = intval($this->keyValue->get('stats_packets_inbound_' . Protocol::TUMBLR) ?? 0);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
|||
use Friendica\Network\HTTPClient\Client\HttpClientRequest;
|
||||
use Friendica\Protocol\ActivityNamespace;
|
||||
use Friendica\Protocol\ActivityPub;
|
||||
use Friendica\Protocol\ATProtocol;
|
||||
use Friendica\Protocol\Diaspora;
|
||||
use Friendica\Protocol\Email;
|
||||
use Friendica\Protocol\Feed;
|
||||
|
|
@ -32,6 +31,7 @@ use Friendica\Util\Crypto;
|
|||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\HTTPSignature;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\ParseUrl;
|
||||
use Friendica\Util\Strings;
|
||||
use Friendica\Util\XML;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
|
|
@ -1189,7 +1189,7 @@ class Probe
|
|||
}
|
||||
|
||||
/**
|
||||
* Check for AT Protocol (Bluesky)
|
||||
* Check for AT Protocol
|
||||
*
|
||||
* @param string $uri Profile link
|
||||
* @return array Profile data or empty array
|
||||
|
|
@ -1221,13 +1221,12 @@ class Probe
|
|||
$name = $profile->displayName ?? $nick;
|
||||
|
||||
$data = [
|
||||
'network' => Protocol::BLUESKY,
|
||||
'network' => Protocol::ATPROTO,
|
||||
'url' => $profile->did,
|
||||
'alias' => ATProtocol::WEB . '/profile/' . $profile->did,
|
||||
'alias' => DI::atpActor()->getProfileLink($profile->did),
|
||||
'name' => $name ?: $nick,
|
||||
'nick' => $nick,
|
||||
'addr' => $nick,
|
||||
'poll' => ATProtocol::WEB . '/profile/' . $profile->did . '/rss',
|
||||
'photo' => $profile->avatar ?? '',
|
||||
];
|
||||
|
||||
|
|
@ -1239,7 +1238,12 @@ class Probe
|
|||
$data['header'] = $profile->banner;
|
||||
}
|
||||
|
||||
$directory = DI::atProtocol()->get(ATProtocol::DIRECTORY . '/' . $profile->did);
|
||||
$profile_page = ParseUrl::getSiteinfoCached($data['alias']);
|
||||
if (isset($profile_page['atprotocol']['feed'])) {
|
||||
$data['poll'] = $profile_page['atprotocol']['feed'];
|
||||
}
|
||||
|
||||
$directory = DI::atProtocol()->get(DI::atProtocol()->getPLCDirectory() . '/' . $profile->did);
|
||||
if (!empty($directory)) {
|
||||
foreach ($directory->service as $service) {
|
||||
if (($service->id == '#atproto_pds') && ($service->type == 'AtprotoPersonalDataServer') && !empty($service->serviceEndpoint)) {
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ class Post
|
|||
$connector = !in_array($item['network'], Protocol::NATIVE_SUPPORT) && ($item['protocol'] != Conversation::PARCEL_JETSTREAM) ? DI::l10n()->t('Connector Message') : false;
|
||||
|
||||
$shareable = in_array($conv->getProfileOwner(), [0, DI::userSession()->getLocalUserId()]) && $item['private'] != Item::PRIVATE;
|
||||
$announceable = $shareable && in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::TWITTER, Protocol::TUMBLR, Protocol::BLUESKY]);
|
||||
$announceable = $shareable && in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::TWITTER, Protocol::TUMBLR, Protocol::ATPROTO]);
|
||||
$commentable = ($item['network'] != Protocol::TUMBLR);
|
||||
$likeable = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
namespace Friendica\Protocol;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMXPath;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
|
||||
use Friendica\Core\Protocol;
|
||||
|
|
@ -18,8 +16,8 @@ use Friendica\Model\User;
|
|||
use Friendica\Network\HTTPClient\Capability\ICanSendHttpRequests;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientRequest;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\ParseUrl;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use stdClass;
|
||||
|
||||
|
|
@ -29,18 +27,19 @@ use stdClass;
|
|||
*/
|
||||
final class ATProtocol
|
||||
{
|
||||
const STATUS_UNKNOWN = 0;
|
||||
const STATUS_TOKEN_OK = 1;
|
||||
const STATUS_SUCCESS = 2;
|
||||
const STATUS_API_FAIL = 10;
|
||||
const STATUS_DID_FAIL = 11;
|
||||
const STATUS_PDS_FAIL = 12;
|
||||
const STATUS_TOKEN_FAIL = 13;
|
||||
public const STATUS_UNKNOWN = 0;
|
||||
public const STATUS_TOKEN_OK = 1;
|
||||
public const STATUS_SUCCESS = 2;
|
||||
public const STATUS_API_FAIL = 10;
|
||||
public const STATUS_DID_FAIL = 11;
|
||||
public const STATUS_PDS_FAIL = 12;
|
||||
public const STATUS_TOKEN_FAIL = 13;
|
||||
|
||||
const APPVIEW_API = 'https://public.api.bsky.app'; // Path to the public Bluesky AppView API.
|
||||
const DIRECTORY = 'https://plc.directory'; // Path to the directory server service to fetch the PDS of a given DID
|
||||
const WEB = 'https://bsky.app'; // Path to the web interface with the user profile and posts
|
||||
const HOSTNAME = 'bsky.social'; // Host name to be added to the handle if incomplete
|
||||
/**
|
||||
* Path to the web interface with the user profile and posts.
|
||||
* This string can then be replaced when displaying the post and profile url.
|
||||
*/
|
||||
public const WEB = 'https://bsky.app';
|
||||
|
||||
/** @var LoggerInterface */
|
||||
private $logger;
|
||||
|
|
@ -57,6 +56,9 @@ final class ATProtocol
|
|||
/** @var ICanSendHttpRequests */
|
||||
private $httpClient;
|
||||
|
||||
private string $api;
|
||||
private int $uid = 0;
|
||||
|
||||
public function __construct(LoggerInterface $logger, Database $database, IManageConfigValues $config, IManagePersonalConfigValues $pConfig, ICanSendHttpRequests $httpClient)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
|
|
@ -67,7 +69,21 @@ final class ATProtocol
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an array of user ids who want to import the Bluesky timeline
|
||||
* Get the AppView API URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getApi(): string
|
||||
{
|
||||
if (!isset($this->api)) {
|
||||
$this->logger->notice('Public API not set.');
|
||||
$this->setApiForUser(0);
|
||||
}
|
||||
return $this->api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of user ids who want to import the AT Protocol timeline
|
||||
*
|
||||
* @return array user ids
|
||||
*/
|
||||
|
|
@ -112,8 +128,12 @@ final class ATProtocol
|
|||
$url .= '?' . http_build_query($parameters);
|
||||
}
|
||||
|
||||
if ($uid == 0) {
|
||||
return $this->get(ATProtocol::APPVIEW_API . '/xrpc/' . $url);
|
||||
if ($uid === 0 && $this->uid !== 0) {
|
||||
$uid = $this->uid;
|
||||
}
|
||||
|
||||
if ($uid === 0) {
|
||||
return $this->get($this->getApi() . '/xrpc/' . $url);
|
||||
}
|
||||
|
||||
$pds = $this->getUserPds($uid);
|
||||
|
|
@ -171,7 +191,7 @@ final class ATProtocol
|
|||
$data = json_decode($curlResult->getBodyString());
|
||||
if (!$curlResult->isSuccess()) {
|
||||
$this->logger->notice('API Error', ['url' => $url, 'code' => $curlResult->getReturnCode(), 'error' => $data ?: $curlResult->getBodyString()]);
|
||||
if (!$data) {
|
||||
if (!$data || !is_object($data)) {
|
||||
return null;
|
||||
}
|
||||
$data->code = $curlResult->getReturnCode();
|
||||
|
|
@ -180,7 +200,7 @@ final class ATProtocol
|
|||
$data->code = $curlResult->getReturnCode();
|
||||
}
|
||||
|
||||
Item::incrementInbound(Protocol::BLUESKY);
|
||||
Item::incrementInbound(Protocol::ATPROTO);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
|
@ -268,7 +288,7 @@ final class ATProtocol
|
|||
private function getUserPds(int $uid): ?string
|
||||
{
|
||||
if ($uid == 0) {
|
||||
return self::APPVIEW_API;
|
||||
return $this->getApi();
|
||||
}
|
||||
|
||||
$pds = $this->pConfig->get($uid, 'bluesky', 'pds');
|
||||
|
|
@ -334,12 +354,8 @@ final class ATProtocol
|
|||
return '';
|
||||
}
|
||||
|
||||
if (strpos($handle, '.') === false) {
|
||||
$handle .= '.' . self::HOSTNAME;
|
||||
}
|
||||
|
||||
// At first we use the AppView API which *should* cover all cases.
|
||||
$data = $this->get(self::APPVIEW_API . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
||||
$data = $this->get($this->getApi() . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
||||
if (!empty($data) && !empty($data->did)) {
|
||||
$this->logger->debug('Got DID by system PDS call', ['handle' => $handle, 'did' => $data->did]);
|
||||
return $data->did;
|
||||
|
|
@ -371,51 +387,8 @@ final class ATProtocol
|
|||
*/
|
||||
public function getDidByProfile(string $url): string
|
||||
{
|
||||
if (preg_match('#^' . self::WEB . '/profile/(.+)#', $url, $matches)) {
|
||||
$did = $this->getDid($matches[1]);
|
||||
if (!empty($did)) {
|
||||
return $did;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$curlResult = $this->httpClient->get($url, HttpClientAccept::HTML, [HttpClientOptions::REQUEST => HttpClientRequest::CONTACTINFO]);
|
||||
} catch (\Throwable $th) {
|
||||
return '';
|
||||
}
|
||||
if (!$curlResult->isSuccess()) {
|
||||
return '';
|
||||
}
|
||||
$profile = $curlResult->getBodyString();
|
||||
if (empty($profile)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$doc = new DOMDocument();
|
||||
try {
|
||||
@$doc->loadHTML($profile);
|
||||
} catch (\Throwable $th) {
|
||||
return '';
|
||||
}
|
||||
$xpath = new DOMXPath($doc);
|
||||
$list = $xpath->query('//p[@id]');
|
||||
foreach ($list as $node) {
|
||||
foreach ($node->attributes as $attribute) {
|
||||
if ($attribute->name == 'id') {
|
||||
$ids[$attribute->value] = $node->textContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($ids['bsky_handle']) || empty($ids['bsky_did'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$this->isValidDid($ids['bsky_did'], $ids['bsky_handle'])) {
|
||||
$this->logger->notice('Invalid DID', ['handle' => $ids['bsky_handle'], 'did' => $ids['bsky_did']]);
|
||||
return '';
|
||||
}
|
||||
|
||||
return $ids['bsky_did'];
|
||||
$data = ParseUrl::getSiteinfoCached($url);
|
||||
return $data['atprotocol']['did'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -473,7 +446,7 @@ final class ATProtocol
|
|||
*/
|
||||
public function getPdsOfDid(string $did): ?string
|
||||
{
|
||||
$data = $this->get(self::DIRECTORY . '/' . $did);
|
||||
$data = $this->get($this->getPLCDirectory() . '/' . $did);
|
||||
if (empty($data) || empty($data->service)) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -487,6 +460,51 @@ final class ATProtocol
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the AppView API for this class for a given uid
|
||||
*
|
||||
* @param integer $uid
|
||||
* @return void
|
||||
*/
|
||||
public function setApiForUser(int $uid)
|
||||
{
|
||||
$this->api = $this->config->get('atprotocol', 'appview_api');
|
||||
if ($uid !== 0 && $this->getUserPds($uid)) {
|
||||
$this->uid = $uid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DID PLC Directory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPLCDirectory(): string
|
||||
{
|
||||
return $this->config->get('atprotocol', 'plc_directory');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Jetstream address
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJetstream(): string
|
||||
{
|
||||
return $this->config->get('atprotocol', 'jetstream');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the web address for a given uid
|
||||
*
|
||||
* @param integer $uid
|
||||
* @return string
|
||||
*/
|
||||
public function getWebForUser(int $uid): string
|
||||
{
|
||||
return $this->pConfig->get($uid, 'bluesky', 'web') ?? $this->config->get('atprotocol', 'web');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided DID matches the handle
|
||||
*
|
||||
|
|
@ -494,9 +512,9 @@ final class ATProtocol
|
|||
* @param string $handle The user handle
|
||||
* @return boolean
|
||||
*/
|
||||
private function isValidDid(string $did, string $handle): bool
|
||||
public function isValidDid(string $did, string $handle): bool
|
||||
{
|
||||
$data = $this->get(self::DIRECTORY . '/' . $did);
|
||||
$data = $this->get($this->getPLCDirectory() . '/' . $did);
|
||||
if (empty($data) || empty($data->alsoKnownAs)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class Actor
|
|||
public function syncContacts(int $uid): void
|
||||
{
|
||||
$this->logger->info('Sync contacts for user - start', ['uid' => $uid]);
|
||||
$contacts = Contact::selectToArray(['id', 'url', 'rel'], ['uid' => $uid, 'network' => Protocol::BLUESKY, 'rel' => [Contact::FRIEND, Contact::SHARING, Contact::FOLLOWER]]);
|
||||
$contacts = Contact::selectToArray(['id', 'url', 'rel'], ['uid' => $uid, 'network' => Protocol::ATPROTO, 'rel' => [Contact::FRIEND, Contact::SHARING, Contact::FOLLOWER]]);
|
||||
|
||||
$follows = [];
|
||||
$cursor = '';
|
||||
|
|
@ -54,7 +54,7 @@ class Actor
|
|||
$parameters = [
|
||||
'actor' => $this->atprotocol->getUserDid($uid),
|
||||
'limit' => 100,
|
||||
'cursor' => $cursor
|
||||
'cursor' => $cursor,
|
||||
];
|
||||
|
||||
$data = $this->atprotocol->XRPCGet('app.bsky.graph.getFollows', $parameters);
|
||||
|
|
@ -72,7 +72,7 @@ class Actor
|
|||
$parameters = [
|
||||
'actor' => $this->atprotocol->getUserDid($uid),
|
||||
'limit' => 100,
|
||||
'cursor' => $cursor
|
||||
'cursor' => $cursor,
|
||||
];
|
||||
|
||||
$data = $this->atprotocol->XRPCGet('app.bsky.graph.getFollowers', $parameters);
|
||||
|
|
@ -117,7 +117,7 @@ class Actor
|
|||
$name = $profile->displayName ?? $nick;
|
||||
|
||||
$fields = [
|
||||
'alias' => ATProtocol::WEB . '/profile/' . $profile->did,
|
||||
'alias' => $this->getProfileLink($profile->did),
|
||||
'name' => $name ?: $nick,
|
||||
'nick' => $nick,
|
||||
'addr' => $nick,
|
||||
|
|
@ -132,7 +132,7 @@ class Actor
|
|||
$fields['header'] = $profile->banner;
|
||||
}
|
||||
|
||||
$directory = $this->atprotocol->get(ATProtocol::DIRECTORY . '/' . $profile->did);
|
||||
$directory = $this->atprotocol->get($this->atprotocol->getPLCDirectory() . '/' . $profile->did);
|
||||
if (!empty($directory->service)) {
|
||||
foreach ($directory->service as $service) {
|
||||
if (($service->id == '#atproto_pds') && ($service->type == 'AtprotoPersonalDataServer') && !empty($service->serviceEndpoint)) {
|
||||
|
|
@ -141,7 +141,7 @@ class Actor
|
|||
}
|
||||
|
||||
if (!empty($fields['baseurl'])) {
|
||||
GServer::check($fields['baseurl'], Protocol::BLUESKY);
|
||||
GServer::check($fields['baseurl'], Protocol::ATPROTO);
|
||||
$fields['gsid'] = GServer::getRealID($fields['baseurl'], true);
|
||||
}
|
||||
|
||||
|
|
@ -154,10 +154,10 @@ class Actor
|
|||
}
|
||||
}
|
||||
|
||||
Contact::update($fields, ['nurl' => $profile->did, 'network' => Protocol::BLUESKY]);
|
||||
Contact::update($fields, ['nurl' => $profile->did, 'network' => Protocol::ATPROTO]);
|
||||
|
||||
if (!empty($profile->avatar)) {
|
||||
$contact = Contact::selectFirst(['id', 'avatar'], ['network' => Protocol::BLUESKY, 'nurl' => $did, 'uid' => 0]);
|
||||
$contact = Contact::selectFirst(['id', 'avatar'], ['network' => Protocol::ATPROTO, 'nurl' => $did, 'uid' => 0]);
|
||||
if (!empty($contact['id']) && ($contact['avatar'] != $profile->avatar)) {
|
||||
Contact::updateAvatar($contact['id'], $profile->avatar);
|
||||
}
|
||||
|
|
@ -175,7 +175,7 @@ class Actor
|
|||
} else {
|
||||
$user_fields = ['rel' => Contact::NOTHING];
|
||||
}
|
||||
Contact::update($user_fields, ['nurl' => $profile->did, 'network' => Protocol::BLUESKY, 'uid' => $contact_uid]);
|
||||
Contact::update($user_fields, ['nurl' => $profile->did, 'network' => Protocol::ATPROTO, 'uid' => $contact_uid]);
|
||||
$this->logger->notice('Update user profile', ['uid' => $contact_uid, 'did' => $profile->did, 'fields' => $user_fields]);
|
||||
}
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ class Actor
|
|||
*/
|
||||
public function getContactByDID(string $did, int $uid, int $contact_uid, bool $auto_update = false): array
|
||||
{
|
||||
$contact = Contact::selectFirst([], ['network' => Protocol::BLUESKY, 'nurl' => $did, 'uid' => [$contact_uid, $uid]], ['order' => ['uid' => true]]);
|
||||
$contact = Contact::selectFirst([], ['network' => Protocol::ATPROTO, 'nurl' => $did, 'uid' => [$contact_uid, $uid]], ['order' => ['uid' => true]]);
|
||||
|
||||
if (!empty($contact) && (!$auto_update || ($contact['updated'] > DateTimeFormat::utc('now -24 hours')))) {
|
||||
return $contact;
|
||||
|
|
@ -200,7 +200,7 @@ class Actor
|
|||
if (empty($contact)) {
|
||||
$fields = [
|
||||
'uid' => $contact_uid,
|
||||
'network' => Protocol::BLUESKY,
|
||||
'network' => Protocol::ATPROTO,
|
||||
'priority' => 1,
|
||||
'writable' => true,
|
||||
'blocked' => false,
|
||||
|
|
@ -208,7 +208,7 @@ class Actor
|
|||
'pending' => false,
|
||||
'url' => $did,
|
||||
'nurl' => $did,
|
||||
'alias' => ATProtocol::WEB . '/profile/' . $did,
|
||||
'alias' => $this->getProfileLink($did),
|
||||
'name' => $did,
|
||||
'nick' => $did,
|
||||
'addr' => $did,
|
||||
|
|
@ -224,4 +224,9 @@ class Actor
|
|||
|
||||
return Contact::getById($cid);
|
||||
}
|
||||
|
||||
public function getProfileLink(string $did): string
|
||||
{
|
||||
return ATProtocol::WEB . '/profile/' . $did;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use Psr\Log\LoggerInterface;
|
|||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class to handle the Bluesky Jetstream firehose
|
||||
* Class to handle the AT Protocol Jetstream firehose
|
||||
*
|
||||
* Existing collections:
|
||||
* app.bsky.feed.like, app.bsky.graph.follow, app.bsky.feed.repost, app.bsky.feed.post, app.bsky.graph.block,
|
||||
|
|
@ -44,18 +44,18 @@ class Jetstream
|
|||
* Maximum drift values in seconds for the threads completion.
|
||||
* If the drift is higher than this value, only a few posts in a thread will be fetched.
|
||||
*/
|
||||
const MAX_DRIFT_THREAD_COMPLETION = 30;
|
||||
public const MAX_DRIFT_THREAD_COMPLETION = 30;
|
||||
/**
|
||||
* Maximum drift values in seconds for the DID cap.
|
||||
* If the drift is higher than this value, the number of DIDs will be capped.
|
||||
*/
|
||||
const MAX_DRIFT_DID_CAP = 60;
|
||||
public const MAX_DRIFT_DID_CAP = 60;
|
||||
/**
|
||||
* Maximum drift values in seconds for creating posts.
|
||||
* If the drift is higher than this value, posts and reshares will not be created.
|
||||
* The other collections will still be processed.
|
||||
*/
|
||||
const MAX_DRIFT_CREATE_POSTS = 1200;
|
||||
public const MAX_DRIFT_CREATE_POSTS = 1200;
|
||||
|
||||
private $uids = [];
|
||||
private $self = [];
|
||||
|
|
@ -90,6 +90,8 @@ class Jetstream
|
|||
$this->atprotocol = $atprotocol;
|
||||
$this->actor = $actor;
|
||||
$this->processor = $processor;
|
||||
|
||||
$this->atprotocol->setApiForUser(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -114,7 +116,7 @@ class Jetstream
|
|||
$this->syncContacts();
|
||||
try {
|
||||
// @todo make the path configurable
|
||||
$this->client = new \WebSocket\Client('wss://jetstream1.us-west.bsky.network/subscribe?requireHello=true' . $cursor);
|
||||
$this->client = new \WebSocket\Client('wss://' . $this->atprotocol->getJetstream() . '/subscribe?requireHello=true' . $cursor);
|
||||
$this->client->setTimeout($timeout);
|
||||
$this->client->setLogger($this->logger);
|
||||
} catch (\WebSocket\ConnectionException $e) {
|
||||
|
|
@ -177,7 +179,7 @@ class Jetstream
|
|||
*/
|
||||
private function incrementMessages(): void
|
||||
{
|
||||
$packets = (int)($this->keyValue->get('jetstream_messages') ?? 0);
|
||||
$packets = (int) ($this->keyValue->get('jetstream_messages') ?? 0);
|
||||
if ($packets >= PHP_INT_MAX) {
|
||||
$packets = 0;
|
||||
}
|
||||
|
|
@ -213,7 +215,7 @@ class Jetstream
|
|||
return;
|
||||
}
|
||||
|
||||
$contacts = Contact::selectToArray(['uid', 'url'], ['uid' => $active_uids, 'network' => Protocol::BLUESKY, 'rel' => [Contact::FRIEND, Contact::SHARING]]);
|
||||
$contacts = Contact::selectToArray(['uid', 'url'], ['uid' => $active_uids, 'network' => Protocol::ATPROTO, 'rel' => [Contact::FRIEND, Contact::SHARING]]);
|
||||
|
||||
$self = [];
|
||||
foreach ($active_uids as $uid) {
|
||||
|
|
@ -233,17 +235,17 @@ class Jetstream
|
|||
|
||||
$dids = array_keys($uids);
|
||||
if (count($dids) > $did_limit) {
|
||||
$contacts = Contact::selectToArray(['url'], ['uid' => $active_uids, 'network' => Protocol::BLUESKY, 'rel' => [Contact::FRIEND, Contact::SHARING]], ['order' => ['last-item' => true]]);
|
||||
$contacts = Contact::selectToArray(['url'], ['uid' => $active_uids, 'network' => Protocol::ATPROTO, 'rel' => [Contact::FRIEND, Contact::SHARING]], ['order' => ['last-item' => true]]);
|
||||
$dids = $this->addDids($contacts, $uids, $did_limit, array_keys($self));
|
||||
}
|
||||
|
||||
if (count($dids) < $did_limit) {
|
||||
$contacts = Contact::selectToArray(['url'], ['uid' => $active_uids, 'network' => Protocol::BLUESKY, 'rel' => Contact::FOLLOWER], ['order' => ['last-item' => true]]);
|
||||
$contacts = Contact::selectToArray(['url'], ['uid' => $active_uids, 'network' => Protocol::ATPROTO, 'rel' => Contact::FOLLOWER], ['order' => ['last-item' => true]]);
|
||||
$dids = $this->addDids($contacts, $uids, $did_limit, $dids);
|
||||
}
|
||||
|
||||
if (!$this->capped && count($dids) < $did_limit) {
|
||||
$condition = ["`uid` = ? AND `network` = ? AND EXISTS(SELECT `author-id` FROM `post-user` WHERE `author-id` = `contact`.`id` AND `post-user`.`uid` != ?)", 0, Protocol::BLUESKY, 0];
|
||||
$condition = ["`uid` = ? AND `network` = ? AND EXISTS(SELECT `author-id` FROM `post-user` WHERE `author-id` = `contact`.`id` AND `post-user`.`uid` != ?)", 0, Protocol::ATPROTO, 0];
|
||||
$contacts = Contact::selectToArray(['url'], $condition, ['order' => ['last-item' => true], 'limit' => $did_limit]);
|
||||
$dids = $this->addDids($contacts, $uids, $did_limit, $dids);
|
||||
}
|
||||
|
|
@ -257,8 +259,8 @@ class Jetstream
|
|||
'payload' => [
|
||||
'wantedCollections' => ['app.bsky.feed.post', 'app.bsky.feed.repost', 'app.bsky.feed.like', 'app.bsky.graph.block', 'app.bsky.actor.profile', 'app.bsky.graph.follow'],
|
||||
'wantedDids' => $dids,
|
||||
'maxMessageSizeBytes' => 1000000
|
||||
]
|
||||
'maxMessageSizeBytes' => 1000000,
|
||||
],
|
||||
];
|
||||
try {
|
||||
$this->client->send(json_encode($update));
|
||||
|
|
@ -271,7 +273,7 @@ class Jetstream
|
|||
* Returns an array of DIDs provided by an array of contacts
|
||||
*
|
||||
* @param array $contacts Array of contact records
|
||||
* @param array $uids Array with the user ids with enabled bluesky timeline import
|
||||
* @param array $uids Array with the user ids with enabled AT Protocol timeline import
|
||||
* @param integer $did_limit Maximum limit of entries
|
||||
* @param array $dids Array of DIDs that are added to the output list
|
||||
* @return array DIDs
|
||||
|
|
@ -306,7 +308,7 @@ class Jetstream
|
|||
]);
|
||||
}
|
||||
|
||||
Item::incrementInbound(Protocol::BLUESKY);
|
||||
Item::incrementInbound(Protocol::ATPROTO);
|
||||
|
||||
switch ($data->kind) {
|
||||
case 'account':
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class Processor
|
|||
|
||||
$this->logger->notice('Process account', ['did' => $data->identity->did, 'fields' => $fields]);
|
||||
|
||||
Contact::update($fields, ['nurl' => $data->identity->did, 'network' => Protocol::BLUESKY]);
|
||||
Contact::update($fields, ['nurl' => $data->identity->did, 'network' => Protocol::ATPROTO]);
|
||||
}
|
||||
|
||||
public function processIdentity(stdClass $data)
|
||||
|
|
@ -77,7 +77,7 @@ class Processor
|
|||
}
|
||||
|
||||
$fields = [
|
||||
'alias' => ATProtocol::WEB . '/profile/' . $data->identity->did,
|
||||
'alias' => $this->actor->getProfileLink($data->identity->did),
|
||||
'nick' => $data->identity->handle,
|
||||
'addr' => $data->identity->handle,
|
||||
'updated' => DateTimeFormat::utc($data->identity->time, DateTimeFormat::MYSQL),
|
||||
|
|
@ -85,7 +85,7 @@ class Processor
|
|||
|
||||
$this->logger->notice('Process identity', ['did' => $data->identity->did, 'fields' => $fields]);
|
||||
|
||||
Contact::update($fields, ['nurl' => $data->identity->did, 'network' => Protocol::BLUESKY]);
|
||||
Contact::update($fields, ['nurl' => $data->identity->did, 'network' => Protocol::ATPROTO]);
|
||||
}
|
||||
|
||||
public function performBlocks(stdClass $data, int $uid)
|
||||
|
|
@ -120,7 +120,7 @@ class Processor
|
|||
return;
|
||||
}
|
||||
|
||||
$condition = ['uri-id' => $itemuri['id'], 'author-link' => $data->did, 'network' => Protocol::BLUESKY];
|
||||
$condition = ['uri-id' => $itemuri['id'], 'author-link' => $data->did, 'network' => Protocol::ATPROTO];
|
||||
if (!Post::exists($condition)) {
|
||||
$this->logger->info('Record not found', $condition);
|
||||
return;
|
||||
|
|
@ -339,7 +339,7 @@ class Processor
|
|||
}
|
||||
|
||||
$item = [
|
||||
'network' => Protocol::BLUESKY,
|
||||
'network' => Protocol::ATPROTO,
|
||||
'protocol' => $protocol,
|
||||
'uid' => $uid,
|
||||
'wall' => false,
|
||||
|
|
@ -404,7 +404,7 @@ class Processor
|
|||
}
|
||||
|
||||
$item = [
|
||||
'network' => Protocol::BLUESKY,
|
||||
'network' => Protocol::ATPROTO,
|
||||
'protocol' => $protocol,
|
||||
'uid' => $uid,
|
||||
'wall' => false,
|
||||
|
|
|
|||
|
|
@ -504,6 +504,8 @@ class ParseUrl
|
|||
}
|
||||
}
|
||||
|
||||
$siteinfo = self::checkATProtocol($siteinfo, $xpath);
|
||||
|
||||
$siteinfo['schematypes'] = [];
|
||||
|
||||
$list = $xpath->query("//script[@type='application/ld+json']");
|
||||
|
|
@ -575,6 +577,90 @@ class ParseUrl
|
|||
return $siteinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the page is a AT protocol profile page or post page
|
||||
*
|
||||
* @param array $siteinfo
|
||||
* @param DOMXPath $xpath
|
||||
* @return array
|
||||
*/
|
||||
private static function checkATProtocol(array $siteinfo, DOMXPath $xpath): array
|
||||
{
|
||||
$handle = '';
|
||||
$list = $xpath->query('//meta[@property]');
|
||||
foreach ($list as $node) {
|
||||
$meta_tag = [];
|
||||
if ($node->attributes->length) {
|
||||
foreach ($node->attributes as $attribute) {
|
||||
$meta_tag[$attribute->name] = $attribute->value;
|
||||
}
|
||||
}
|
||||
if ($meta_tag['property'] !== 'profile:username' || !isset($meta_tag['content'])) {
|
||||
continue;
|
||||
}
|
||||
$handle = $meta_tag['content'];
|
||||
}
|
||||
if ($handle === '') {
|
||||
return $siteinfo;
|
||||
}
|
||||
|
||||
$siteinfo['atprotocol']['handle'] = $handle;
|
||||
|
||||
// Publically visible posts have got a link element that points to the at address
|
||||
$list = $xpath->query('//link[@rel]');
|
||||
foreach ($list as $node) {
|
||||
$meta_tag = [];
|
||||
if ($node->attributes->length) {
|
||||
foreach ($node->attributes as $attribute) {
|
||||
$meta_tag[$attribute->name] = $attribute->value;
|
||||
}
|
||||
}
|
||||
if ($meta_tag['rel'] !== 'alternate' || !isset($meta_tag['href'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($meta_tag['type']) && $meta_tag['type'] === 'application/rss+xml') {
|
||||
$siteinfo['atprotocol']['feed'] = $meta_tag['href'];
|
||||
}
|
||||
|
||||
if (!str_starts_with($meta_tag['href'], 'at://')) {
|
||||
continue;
|
||||
}
|
||||
if (str_ends_with($meta_tag['href'], '/app.bsky.actor.profile/self')) {
|
||||
$siteinfo['atprotocol']['did'] = str_replace(['at://', '/app.bsky.actor.profile/self'], '', $meta_tag['href']);
|
||||
DI::logger()->debug('Found AT Protocol post via alternate link', ['url' => $siteinfo['url'], 'uri' => $meta_tag['href']]);
|
||||
continue;
|
||||
}
|
||||
$siteinfo['atprotocol']['uri'] = $meta_tag['href'];
|
||||
$parts = explode('/', $siteinfo['atprotocol']['uri']);
|
||||
if (count($parts) === 5) {
|
||||
$siteinfo['atprotocol']['did'] = $parts[2];
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($siteinfo['atprotocol']['did'])) {
|
||||
$did = DI::atProtocol()->getDid($handle);
|
||||
if ($did === '') {
|
||||
unset($siteinfo['atprotocol']);
|
||||
return $siteinfo;
|
||||
}
|
||||
$siteinfo['atprotocol']['did'] = $did;
|
||||
}
|
||||
|
||||
if (!DI::atProtocol()->isValidDid($siteinfo['atprotocol']['did'], $siteinfo['atprotocol']['handle'])) {
|
||||
unset($siteinfo['atprotocol']);
|
||||
return $siteinfo;
|
||||
}
|
||||
|
||||
// When the post is not publically visible, we have to do some guess work. At first we check if that page is an AT Protocol page
|
||||
if (!isset($siteinfo['atprotocol']['uri']) && preg_match('#^https://.+/profile/(.+)/post/(.+)#', $siteinfo['url'], $matches)) {
|
||||
$siteinfo['atprotocol']['uri'] = 'at://' . $siteinfo['atprotocol']['did'] . '/app.bsky.feed.post/' . $matches[2];
|
||||
DI::logger()->debug('Found AT Protocol post via url structure', ['uri' => $siteinfo['url'], 'did' => $siteinfo['atprotocol']['did'], 'cid' => $matches[2]]);
|
||||
}
|
||||
|
||||
return $siteinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the attached media elements.
|
||||
* Fix existing data and add missing data.
|
||||
|
|
@ -836,6 +922,10 @@ class ParseUrl
|
|||
return $siteinfo;
|
||||
}
|
||||
|
||||
if (isset($siteinfo['atprotocol']) && $type === 'ProfilePage') {
|
||||
$siteinfo = self::parseJsonLdProfilePage($siteinfo, $jsonld);
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case 'Article':
|
||||
case 'AdvertiserContentArticle':
|
||||
|
|
@ -907,6 +997,41 @@ class ParseUrl
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch AT Protocol related profile page data
|
||||
*
|
||||
* @param array $siteinfo
|
||||
* @param array $jsonld
|
||||
*
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLdProfilePage(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
if (isset($jsonld['dateCreated'])) {
|
||||
$siteinfo['atprotocol']['created'] = DateTimeFormat::utc($jsonld['dateCreated']);
|
||||
}
|
||||
if (!isset($jsonld['mainEntity']) || !is_array($jsonld['mainEntity'])) {
|
||||
return $siteinfo;
|
||||
}
|
||||
$main = $jsonld['mainEntity'];
|
||||
if (!isset($main['@type']) || $main['@type'] !== 'Person') {
|
||||
return $siteinfo;
|
||||
}
|
||||
if (isset($main['name'])) {
|
||||
$siteinfo['atprotocol']['name'] = $main['name'];
|
||||
}
|
||||
if (isset($main['identifier'])) {
|
||||
$siteinfo['atprotocol']['did'] = $main['identifier'];
|
||||
}
|
||||
if (isset($main['description'])) {
|
||||
$siteinfo['atprotocol']['description'] = $main['description'];
|
||||
}
|
||||
if (isset($main['image'])) {
|
||||
$siteinfo['atprotocol']['image'] = $main['image'];
|
||||
}
|
||||
return $siteinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch author and publisher data
|
||||
*
|
||||
|
|
|
|||
|
|
@ -147,15 +147,16 @@ class Strings
|
|||
*
|
||||
* @param string $network Network name of the contact (e.g. dfrn, rss and so on)
|
||||
* @param string $url The contact url
|
||||
* @param int $gsid Server id
|
||||
*
|
||||
* @return string Formatted network name
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function formatNetworkName(string $network, string $url = ''): string
|
||||
public static function formatNetworkName(string $network, string $url = '', ?int $gsid = null): string
|
||||
{
|
||||
if ($network != '') {
|
||||
if ($url != '') {
|
||||
$gsid = ContactSelector::getServerIdForProfile($url);
|
||||
$gsid = $gsid ?? ContactSelector::getServerIdForProfile($url);
|
||||
$network_name = '<a href="' . $url . '">' . ContactSelector::networkToName($network, '', $gsid) . '</a>';
|
||||
} else {
|
||||
$network_name = ContactSelector::networkToName($network);
|
||||
|
|
|
|||
|
|
@ -792,4 +792,20 @@ return [
|
|||
// The higher the number, the more likely the system won't be able to process the posts on time.
|
||||
'did_limit' => 1000,
|
||||
],
|
||||
'atprotocol' => [
|
||||
// appview_api (URL)
|
||||
// Path to the public Bluesky AppView API.
|
||||
'appview_api' => 'https://public.api.bsky.app',
|
||||
// jetstream (URL)
|
||||
// Path to the jetstream service. Available servers are:
|
||||
// jetstream1.us-east.bsky.network, jetstream2.us-east.bsky.network, jetstream1.us-west.bsky.network, jetstream2.us-west.bsky.network
|
||||
'jetstream' => 'jetstream1.us-west.bsky.network',
|
||||
// directory (URL)
|
||||
// Path to the directory server service to fetch the PDS of a given DID
|
||||
'plc_directory' => 'https://plc.directory',
|
||||
// web (URL)
|
||||
// Path to the web interface with the user profile and posts.
|
||||
// Other options are https://reddwarf.app or https://blacksky.community
|
||||
'web' => 'https://bsky.app',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class PlaintextTest extends FixtureTestCase
|
|||
'Wenn die Person noch nichts gepostet hat, ignoriere ich die Anfragen und schaue ggf. nach einiger Zeit wieder nach, ob jetzt was gepostet wurde! (3/6)',
|
||||
'Wenn die Posts in eine Richtung gehen, die ich nicht mag, lehne ich die Anfragen ab. (4/6)',
|
||||
'Ich ignoriere auch Anfragen, wenn sie von Accounts kommen, die ggf. tausenden von anderen Accounts folgen, da ich davon ausgehe, (5/6)',
|
||||
'dass da niemand ernsthaft so vielen Accounts folgen kann. (6/6)'
|
||||
'dass da niemand ernsthaft so vielen Accounts folgen kann. (6/6)',
|
||||
],
|
||||
],
|
||||
'test-2' => [
|
||||
|
|
@ -41,7 +41,7 @@ class PlaintextTest extends FixtureTestCase
|
|||
'Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. (3/6)',
|
||||
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, (4/6)',
|
||||
'sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. (5/6)',
|
||||
'Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. (6/6)'
|
||||
'Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. (6/6)',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
@ -66,7 +66,7 @@ class PlaintextTest extends FixtureTestCase
|
|||
'plink' => '',
|
||||
'body' => $text,
|
||||
];
|
||||
$output = Plaintext::getPost($item, 160, false, BBCode::BLUESKY);
|
||||
$output = Plaintext::getPost($item, 160, false, BBCode::ATPROTOCOL);
|
||||
self::assertEquals($expected, $output['parts']);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: 2026.04-dev\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-03-04 20:06+0100\n"
|
||||
"POT-Creation-Date: 2026-03-15 22:51+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -262,7 +262,7 @@ msgstr ""
|
|||
msgid "Failed to delete the photo."
|
||||
msgstr ""
|
||||
|
||||
#: mod/photos.php:332 src/Module/Conversation/Community.php:150
|
||||
#: mod/photos.php:332 src/Module/Conversation/Community.php:145
|
||||
#: src/Module/Directory.php:34 src/Module/Profile/Photos.php:270
|
||||
#: src/Module/Search/Index.php:50
|
||||
msgid "Public access denied."
|
||||
|
|
@ -917,7 +917,7 @@ msgid "Tumblr"
|
|||
msgstr ""
|
||||
|
||||
#: src/Content/ContactSelector.php:137
|
||||
msgid "Bluesky"
|
||||
msgid "AT Protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/ContactSelector.php:165
|
||||
|
|
@ -1182,7 +1182,7 @@ msgid "Preview"
|
|||
msgstr ""
|
||||
|
||||
#: src/Content/Conversation.php:429 src/Content/Item.php:442
|
||||
#: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1307
|
||||
#: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1306
|
||||
#: src/Model/Profile.php:472 src/Module/Admin/Logs/View.php:79
|
||||
#: src/Module/Post/Edit.php:181
|
||||
msgid "Message"
|
||||
|
|
@ -1538,7 +1538,7 @@ msgid "Display posts that have been created by accounts of the selected circle."
|
|||
msgstr ""
|
||||
|
||||
#: src/Content/Feature.php:128 src/Content/GroupManager.php:131
|
||||
#: src/Content/Nav.php:275 src/Content/Text/HTML.php:877
|
||||
#: src/Content/Nav.php:275 src/Content/Text/HTML.php:884
|
||||
#: src/Content/Widget.php:564 src/Model/User.php:1400
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
|
@ -1598,7 +1598,7 @@ msgstr ""
|
|||
msgid "Display a list of folders in which posts are stored."
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Feature.php:135 src/Module/Conversation/Timeline.php:188
|
||||
#: src/Content/Feature.php:135 src/Module/Conversation/Timeline.php:189
|
||||
msgid "Own Contacts"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1693,27 +1693,27 @@ msgstr ""
|
|||
msgid "Complete Thread"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:437 src/Model/Contact.php:1302
|
||||
#: src/Content/Item.php:437 src/Model/Contact.php:1301
|
||||
msgid "View Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:438 src/Content/Item.php:461 src/Model/Contact.php:1237
|
||||
#: src/Model/Contact.php:1293 src/Model/Contact.php:1303
|
||||
#: src/Content/Item.php:438 src/Content/Item.php:461 src/Model/Contact.php:1236
|
||||
#: src/Model/Contact.php:1292 src/Model/Contact.php:1302
|
||||
#: src/Module/Directory.php:143 src/Module/Settings/Profile/Index.php:279
|
||||
msgid "View Profile"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:439 src/Model/Contact.php:1304
|
||||
#: src/Content/Item.php:439 src/Model/Contact.php:1303
|
||||
msgid "View Photos"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:440 src/Model/Contact.php:1271
|
||||
#: src/Content/Item.php:440 src/Model/Contact.php:1270
|
||||
#: src/Model/Profile.php:444
|
||||
msgid "Network Posts"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:441 src/Model/Contact.php:1295
|
||||
#: src/Model/Contact.php:1306
|
||||
#: src/Content/Item.php:441 src/Model/Contact.php:1294
|
||||
#: src/Model/Contact.php:1305
|
||||
msgid "View Contact"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1751,7 +1751,7 @@ msgid "Raw content"
|
|||
msgstr ""
|
||||
|
||||
#: src/Content/Item.php:458 src/Content/Widget.php:71
|
||||
#: src/Model/Contact.php:1296 src/Model/Contact.php:1308
|
||||
#: src/Model/Contact.php:1295 src/Model/Contact.php:1307
|
||||
#: src/Module/Contact/Follow.php:152 view/theme/vier/theme.php:182
|
||||
msgid "Connect/Follow"
|
||||
msgstr ""
|
||||
|
|
@ -1902,7 +1902,7 @@ msgstr ""
|
|||
msgid "Addon applications, utilities, games"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:266 src/Content/Text/HTML.php:862
|
||||
#: src/Content/Nav.php:266 src/Content/Text/HTML.php:869
|
||||
#: src/Module/Search/Index.php:99
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
|
@ -1911,17 +1911,17 @@ msgstr ""
|
|||
msgid "Search site content"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:269 src/Content/Text/HTML.php:871
|
||||
#: src/Content/Nav.php:269 src/Content/Text/HTML.php:878
|
||||
msgid "Full Text"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:270 src/Content/Text/HTML.php:872
|
||||
#: src/Content/Nav.php:270 src/Content/Text/HTML.php:879
|
||||
#: src/Content/Widget/TagCloud.php:54
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:271 src/Content/Nav.php:326
|
||||
#: src/Content/Text/HTML.php:873 src/Module/BaseProfile.php:112
|
||||
#: src/Content/Nav.php:271 src/Content/Nav.php:330
|
||||
#: src/Content/Text/HTML.php:880 src/Module/BaseProfile.php:112
|
||||
#: src/Module/BaseProfile.php:115 src/Module/Contact.php:181
|
||||
#: src/Module/Contact.php:411 src/Module/Contact.php:521
|
||||
#: view/theme/frio/theme.php:231
|
||||
|
|
@ -2013,7 +2013,7 @@ msgstr ""
|
|||
msgid "Outbox"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:321
|
||||
#: src/Content/Nav.php:320
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -2021,30 +2021,30 @@ msgstr ""
|
|||
msgid "Manage other accounts, including groups and pages"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:324 src/Module/Admin/Addons/Details.php:140
|
||||
#: src/Content/Nav.php:328 src/Module/Admin/Addons/Details.php:140
|
||||
#: src/Module/Admin/Themes/Details.php:85 src/Module/BaseAdmin.php:88
|
||||
#: src/Module/BaseSettings.php:177 src/Module/Welcome.php:39
|
||||
#: view/theme/frio/theme.php:230
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:324 view/theme/frio/theme.php:230
|
||||
#: src/Content/Nav.php:328 view/theme/frio/theme.php:230
|
||||
msgid "Account settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:326 view/theme/frio/theme.php:231
|
||||
#: src/Content/Nav.php:330 view/theme/frio/theme.php:231
|
||||
msgid "Manage/edit friends and contacts"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:331 src/Module/BaseAdmin.php:114
|
||||
#: src/Content/Nav.php:335 src/Module/BaseAdmin.php:114
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:331
|
||||
#: src/Content/Nav.php:335
|
||||
msgid "Site setup and configuration"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:332 src/Module/BaseModeration.php:117
|
||||
#: src/Content/Nav.php:336 src/Module/BaseModeration.php:117
|
||||
#: src/Module/Moderation/Blocklist/Contact.php:98
|
||||
#: src/Module/Moderation/Blocklist/Contact/Import.php:101
|
||||
#: src/Module/Moderation/Blocklist/Server/Add.php:110
|
||||
|
|
@ -2061,15 +2061,15 @@ msgstr ""
|
|||
msgid "Moderation"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:332
|
||||
#: src/Content/Nav.php:336
|
||||
msgid "Content and user moderation"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:335
|
||||
#: src/Content/Nav.php:339
|
||||
msgid "Navigation"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Nav.php:335
|
||||
#: src/Content/Nav.php:339
|
||||
msgid "Site map"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -2089,49 +2089,49 @@ msgstr ""
|
|||
msgid "last"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/BBCode.php:917
|
||||
#: src/Content/Text/BBCode.php:923
|
||||
#, php-format
|
||||
msgid "<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">%2$s</a> %3$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/BBCode.php:945 src/Model/Item.php:3750
|
||||
#: src/Content/Text/BBCode.php:951 src/Model/Item.php:3750
|
||||
#: src/Model/Item.php:3756 src/Model/Item.php:3757
|
||||
msgid "Link to source"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/BBCode.php:1735 src/Content/Text/HTML.php:901
|
||||
#: src/Content/Text/BBCode.php:1741 src/Content/Text/HTML.php:908
|
||||
msgid "Click to open/close"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/BBCode.php:1790
|
||||
#: src/Content/Text/BBCode.php:1796
|
||||
msgid "$1 wrote:"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/BBCode.php:1864 src/Content/Text/BBCode.php:1865
|
||||
#: src/Content/Text/BBCode.php:1870 src/Content/Text/BBCode.php:1871
|
||||
msgid "Encrypted content"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/BBCode.php:2181
|
||||
#: src/Content/Text/BBCode.php:2187
|
||||
msgid "Invalid source protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/BBCode.php:2200
|
||||
#: src/Content/Text/BBCode.php:2206
|
||||
msgid "Invalid link protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/HTML.php:779
|
||||
#: src/Content/Text/HTML.php:786
|
||||
msgid "Loading more entries..."
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/HTML.php:780
|
||||
#: src/Content/Text/HTML.php:787
|
||||
msgid "The end"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/HTML.php:856
|
||||
#: src/Content/Text/HTML.php:863
|
||||
msgid "Save search"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Text/HTML.php:864
|
||||
#: src/Content/Text/HTML.php:871
|
||||
msgid "@name, !group, #tags, content"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -2249,7 +2249,7 @@ msgstr ""
|
|||
msgid "Organisations"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Widget.php:563 src/Model/Contact.php:1814
|
||||
#: src/Content/Widget.php:563 src/Model/Contact.php:1797
|
||||
msgid "News"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -2311,12 +2311,12 @@ msgstr ""
|
|||
msgid "Show Less"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Widget/VCard.php:94 src/Model/Contact.php:1265
|
||||
#: src/Content/Widget/VCard.php:94 src/Model/Contact.php:1264
|
||||
#: src/Model/Profile.php:438
|
||||
msgid "Post to group"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Widget/VCard.php:99 src/Model/Contact.php:1269
|
||||
#: src/Content/Widget/VCard.php:99 src/Model/Contact.php:1268
|
||||
#: src/Model/Profile.php:442 src/Module/Moderation/Item/Source.php:81
|
||||
msgid "Mention"
|
||||
msgstr ""
|
||||
|
|
@ -2349,13 +2349,13 @@ msgstr ""
|
|||
msgid "Follow"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1297
|
||||
#: src/Model/Contact.php:1309 src/Model/Profile.php:468
|
||||
#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1296
|
||||
#: src/Model/Contact.php:1308 src/Model/Profile.php:468
|
||||
#: src/Module/Contact/Profile.php:521
|
||||
msgid "Unfollow"
|
||||
msgstr ""
|
||||
|
||||
#: src/Content/Widget/VCard.php:124 src/Model/Contact.php:1267
|
||||
#: src/Content/Widget/VCard.php:124 src/Model/Contact.php:1266
|
||||
#: src/Model/Profile.php:440
|
||||
msgid "View group"
|
||||
msgstr ""
|
||||
|
|
@ -2900,83 +2900,83 @@ msgstr ""
|
|||
msgid "Edit circles"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:1316 src/Module/Moderation/Users/Pending.php:88
|
||||
#: src/Model/Contact.php:1315 src/Module/Moderation/Users/Pending.php:88
|
||||
#: src/Module/Notifications/Introductions.php:128
|
||||
msgid "Approve"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:1658 src/Model/Contact.php:1730
|
||||
#: src/Model/Contact.php:1653 src/Model/Contact.php:1718
|
||||
#: src/Module/Contact/Profile.php:399
|
||||
#, php-format
|
||||
msgid "%s has blocked you"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:1810
|
||||
#: src/Model/Contact.php:1793
|
||||
msgid "Organisation"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:1818
|
||||
#: src/Model/Contact.php:1801
|
||||
msgid "Group"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:1822 src/Module/Moderation/BaseUsers.php:150
|
||||
#: src/Model/Contact.php:1805 src/Module/Moderation/BaseUsers.php:150
|
||||
msgid "Relay"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3152
|
||||
#: src/Model/Contact.php:3131
|
||||
msgid "Disallowed profile URL."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3157 src/Module/Friendica.php:106
|
||||
#: src/Model/Contact.php:3136 src/Module/Friendica.php:106
|
||||
msgid "Blocked domain"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3162
|
||||
#: src/Model/Contact.php:3141
|
||||
msgid "Connect URL missing."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3175
|
||||
#: src/Model/Contact.php:3154
|
||||
msgid "The contact could not be added. Please check the relevant network credentials in your Settings -> Social Networks page."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3193
|
||||
#: src/Model/Contact.php:3172
|
||||
#, php-format
|
||||
msgid "Expected network %s does not match actual network %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3210
|
||||
#: src/Model/Contact.php:3189
|
||||
msgid "This seems to be a relay account. They can't be followed by users."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3217
|
||||
#: src/Model/Contact.php:3196
|
||||
msgid "The profile address specified does not provide adequate information."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3219
|
||||
#: src/Model/Contact.php:3198
|
||||
msgid "No compatible communication protocols or feeds were discovered."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3222
|
||||
#: src/Model/Contact.php:3201
|
||||
msgid "An author or name was not found."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3225
|
||||
#: src/Model/Contact.php:3204
|
||||
msgid "No browser URL could be matched to this address."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3228
|
||||
#: src/Model/Contact.php:3207
|
||||
msgid "Unable to match @-style Identity Address with a known protocol or email contact."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3229
|
||||
#: src/Model/Contact.php:3208
|
||||
msgid "Use mailto: in front of address to force email check."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3235
|
||||
#: src/Model/Contact.php:3214
|
||||
msgid "Limited profile. This person will be unable to receive direct/personal notifications from you."
|
||||
msgstr ""
|
||||
|
||||
#: src/Model/Contact.php:3294
|
||||
#: src/Model/Contact.php:3273
|
||||
msgid "Unable to retrieve contact information."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3699,7 +3699,7 @@ msgstr ""
|
|||
|
||||
#: src/Module/Admin/Addons/Details.php:137 src/Module/Admin/Addons/Index.php:83
|
||||
#: src/Module/Admin/Federation.php:218 src/Module/Admin/Logs/Settings.php:74
|
||||
#: src/Module/Admin/Logs/View.php:71 src/Module/Admin/Queue.php:59
|
||||
#: src/Module/Admin/Logs/View.php:71 src/Module/Admin/Queue.php:64
|
||||
#: src/Module/Admin/Site.php:457 src/Module/Admin/Storage.php:123
|
||||
#: src/Module/Admin/Summary.php:206 src/Module/Admin/Themes/Details.php:82
|
||||
#: src/Module/Admin/Themes/Index.php:103 src/Module/Admin/Tos.php:63
|
||||
|
|
@ -4063,28 +4063,28 @@ msgstr ""
|
|||
msgid "This page lists the currently queued worker jobs. These jobs are handled by the worker cronjob you've set up during install."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Queue.php:62
|
||||
#: src/Module/Admin/Queue.php:67
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Queue.php:63
|
||||
#: src/Module/Admin/Queue.php:68
|
||||
msgid "Command"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Queue.php:64
|
||||
#: src/Module/Admin/Queue.php:69
|
||||
msgid "Job Parameters"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Queue.php:65 src/Module/Moderation/Reports.php:110
|
||||
#: src/Module/Admin/Queue.php:70 src/Module/Moderation/Reports.php:110
|
||||
#: src/Module/Settings/OAuth.php:60
|
||||
msgid "Created"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Queue.php:66
|
||||
#: src/Module/Admin/Queue.php:71
|
||||
msgid "Next Try"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Admin/Queue.php:67
|
||||
#: src/Module/Admin/Queue.php:72
|
||||
msgid "Priority"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -5605,9 +5605,9 @@ msgid "Tips for New Members"
|
|||
msgstr ""
|
||||
|
||||
#: src/Module/BaseProfile.php:141 src/Module/Contact.php:395
|
||||
#: src/Module/Contact.php:542 src/Module/Conversation/Channel.php:98
|
||||
#: src/Module/Conversation/Community.php:91
|
||||
#: src/Module/Conversation/Network.php:384
|
||||
#: src/Module/Contact.php:542 src/Module/Conversation/Channel.php:93
|
||||
#: src/Module/Conversation/Community.php:86
|
||||
#: src/Module/Conversation/Network.php:379
|
||||
#: src/Module/Moderation/BaseUsers.php:130 src/Object/Post.php:618
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
|
@ -5622,8 +5622,8 @@ msgstr ""
|
|||
msgid "Group Search - %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/BaseSearch.php:115 src/Module/Conversation/Channel.php:125
|
||||
#: src/Module/Conversation/Community.php:115 src/Module/Search/Index.php:140
|
||||
#: src/Module/BaseSearch.php:115 src/Module/Conversation/Channel.php:120
|
||||
#: src/Module/Conversation/Community.php:110 src/Module/Search/Index.php:140
|
||||
#: src/Module/Search/Index.php:192
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
|
|
@ -5987,7 +5987,7 @@ msgstr ""
|
|||
msgid "Search your contacts"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Contact.php:444 src/Module/Search/Index.php:206
|
||||
#: src/Module/Contact.php:444 src/Module/Search/Index.php:201
|
||||
#, php-format
|
||||
msgid "Results for: %s"
|
||||
msgstr ""
|
||||
|
|
@ -6159,7 +6159,7 @@ msgstr[0] ""
|
|||
msgstr[1] ""
|
||||
|
||||
#: src/Module/Contact/Follow.php:56 src/Module/Contact/Redir.php:47
|
||||
#: src/Module/Contact/Redir.php:208 src/Module/Conversation/Community.php:156
|
||||
#: src/Module/Contact/Redir.php:208 src/Module/Conversation/Community.php:151
|
||||
#: src/Module/Debug/ItemBody.php:30 src/Module/Diaspora/Receive.php:45
|
||||
#: src/Module/Item/Complete.php:25 src/Module/Item/Display.php:84
|
||||
#: src/Module/Item/Feed.php:45 src/Module/Item/Follow.php:27
|
||||
|
|
@ -6579,7 +6579,7 @@ msgstr ""
|
|||
msgid "Unable to unfollow this contact, please contact your administrator"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Channel.php:163
|
||||
#: src/Module/Conversation/Channel.php:158
|
||||
msgid "Channel not available."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -6587,37 +6587,37 @@ msgstr ""
|
|||
msgid "This community stream shows all public posts received by this node. They may not reflect the opinions of this node’s users."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Community.php:170
|
||||
#: src/Module/Conversation/Community.php:165
|
||||
msgid "Community option not available."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Community.php:186
|
||||
#: src/Module/Conversation/Community.php:181
|
||||
msgid "Not available."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Network.php:276
|
||||
#: src/Module/Conversation/Network.php:271
|
||||
msgid "No such circle"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Network.php:280
|
||||
#: src/Module/Conversation/Network.php:275
|
||||
#, php-format
|
||||
msgid "Circle: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Network.php:300
|
||||
#: src/Module/Conversation/Network.php:295
|
||||
#, php-format
|
||||
msgid "Error %d (%s) while fetching the timeline."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Network.php:396
|
||||
#: src/Module/Conversation/Network.php:391
|
||||
msgid "Network feed not available."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Timeline.php:192
|
||||
#: src/Module/Conversation/Timeline.php:193
|
||||
msgid "Include"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Conversation/Timeline.php:193
|
||||
#: src/Module/Conversation/Timeline.php:194
|
||||
msgid "Hide"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -7113,15 +7113,15 @@ msgstr ""
|
|||
msgid "Unable to follow this item."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:50
|
||||
#: src/Module/LostPass.php:76
|
||||
msgid "No valid account found."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:62
|
||||
#: src/Module/LostPass.php:88
|
||||
msgid "Password reset request issued. Check your email."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:68
|
||||
#: src/Module/LostPass.php:94
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
|
@ -7137,7 +7137,7 @@ msgid ""
|
|||
"\t\t\tissued this request."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:79
|
||||
#: src/Module/LostPass.php:105
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
|
@ -7154,64 +7154,64 @@ msgid ""
|
|||
"\t\t\tLogin Name:\t%3$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:93
|
||||
#: src/Module/LostPass.php:119
|
||||
#, php-format
|
||||
msgid "Password reset requested at %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:109
|
||||
#: src/Module/LostPass.php:141
|
||||
msgid "Request could not be verified. (You may have previously submitted it.) Password reset failed."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:122
|
||||
#: src/Module/LostPass.php:154
|
||||
msgid "Request has expired, please make a new one."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:137
|
||||
#: src/Module/LostPass.php:174
|
||||
msgid "Forgot your Password?"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:138
|
||||
#: src/Module/LostPass.php:175
|
||||
msgid "Enter your email address and submit to have your password reset. Then check your email for further instructions."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:139 src/Module/Security/Login.php:167
|
||||
#: src/Module/LostPass.php:176 src/Module/Security/Login.php:167
|
||||
msgid "Nickname or email"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:140
|
||||
#: src/Module/LostPass.php:177
|
||||
msgid "Reset my password"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:155 src/Module/Security/Login.php:179
|
||||
#: src/Module/LostPass.php:198 src/Module/Security/Login.php:179
|
||||
msgid "Password Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:156
|
||||
#: src/Module/LostPass.php:199
|
||||
msgid "Your password has been reset as requested."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:157
|
||||
#: src/Module/LostPass.php:200
|
||||
msgid "Your new password is"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:158
|
||||
#: src/Module/LostPass.php:201
|
||||
msgid "Save or copy your new password - and then"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:159
|
||||
#: src/Module/LostPass.php:202
|
||||
msgid "click here to login"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:160
|
||||
#: src/Module/LostPass.php:203
|
||||
msgid "Your password may be changed from the <em>Settings</em> page after successful login."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:164
|
||||
#: src/Module/LostPass.php:207
|
||||
msgid "Your password has been reset."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:167
|
||||
#: src/Module/LostPass.php:210
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
|
@ -7222,7 +7222,7 @@ msgid ""
|
|||
"\t\t\t"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:173
|
||||
#: src/Module/LostPass.php:216
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
|
@ -7236,7 +7236,7 @@ msgid ""
|
|||
"\t\t\t"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/LostPass.php:184
|
||||
#: src/Module/LostPass.php:227
|
||||
#, php-format
|
||||
msgid "Your password has been changed at %s"
|
||||
msgstr ""
|
||||
|
|
@ -8352,11 +8352,11 @@ msgstr ""
|
|||
msgid "Show unread"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Notifications/Ping.php:208
|
||||
#: src/Module/Notifications/Ping.php:211
|
||||
msgid "{0} requested registration"
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Notifications/Ping.php:217
|
||||
#: src/Module/Notifications/Ping.php:220
|
||||
#, php-format
|
||||
msgid "{0} and %d others requested registration"
|
||||
msgstr ""
|
||||
|
|
@ -8903,7 +8903,7 @@ msgstr ""
|
|||
msgid "Only one search per minute is permitted for not logged in users."
|
||||
msgstr ""
|
||||
|
||||
#: src/Module/Search/Index.php:204
|
||||
#: src/Module/Search/Index.php:199
|
||||
#, php-format
|
||||
msgid "Items tagged with: %s"
|
||||
msgstr ""
|
||||
|
|
|
|||