diff --git a/REUSE.toml b/REUSE.toml index b7e959535b..8f305ad303 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -260,6 +260,11 @@ path = "view/js/hls/**" SPDX-FileCopyrightText = "2017 Dailymotion (http://www.dailymotion.com)" SPDX-License-Identifier = "Apache-2.0" +[[annotations]] +path = "view/js/videojs/**" +SPDX-FileCopyrightText = "Copyright 2010-present Video.js contributors" +SPDX-License-Identifier = "Apache-2.0" + [[annotations]] path = [ "images/rm-16.png", "images/rhash-16.png"] SPDX-FileCopyrightText = "Red Matrix Project" diff --git a/database.sql b/database.sql index 45cb0c7274..e84a62bbfc 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2025.07-rc (Interrupted Fern) --- DB_UPDATE_VERSION 1582 +-- DB_UPDATE_VERSION 1584 -- ------------------------------------------ @@ -1275,7 +1275,7 @@ CREATE TABLE IF NOT EXISTS `post-collection` ( CREATE TABLE IF NOT EXISTS `post-content` ( `uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri', `title` varchar(255) NOT NULL DEFAULT '' COMMENT 'item title', - `content-warning` varchar(255) NOT NULL DEFAULT '' COMMENT '', + `content-warning` varchar(500) NOT NULL DEFAULT '' COMMENT '', `body` mediumtext COMMENT 'item body content', `raw-body` mediumtext COMMENT 'Body without embedded media links', `quote-uri-id` int unsigned COMMENT 'Id of the item-uri table that contains the quoted uri', @@ -1368,12 +1368,14 @@ CREATE TABLE IF NOT EXISTS `post-history` ( `uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri', `edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of edit', `title` varchar(255) NOT NULL DEFAULT '' COMMENT 'item title', - `content-warning` varchar(255) NOT NULL DEFAULT '' COMMENT '', + `content-warning` varchar(500) NOT NULL DEFAULT '' COMMENT '', `body` mediumtext COMMENT 'item body content', `raw-body` mediumtext COMMENT 'Body without embedded media links', + `quote-uri-id` int unsigned COMMENT 'Id of the item-uri table that contains the quoted uri', `location` varchar(255) NOT NULL DEFAULT '' COMMENT 'text location where this item originated', `coord` varchar(255) NOT NULL DEFAULT '' COMMENT 'longitude/latitude pair representing location where this item originated', `language` text COMMENT 'Language information about this post', + `sensitive` boolean COMMENT 'If true, this post contains sensitive content', `app` varchar(255) NOT NULL DEFAULT '' COMMENT 'application which generated this item', `rendered-hash` varchar(32) NOT NULL DEFAULT '' COMMENT '', `rendered-html` mediumtext COMMENT 'item.body converted to html', @@ -1384,7 +1386,9 @@ CREATE TABLE IF NOT EXISTS `post-history` ( `resource-id` varchar(32) NOT NULL DEFAULT '' COMMENT 'Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type', `plink` varbinary(383) NOT NULL DEFAULT '' COMMENT 'permalink or URL to a displayable copy of the message at its source', PRIMARY KEY(`uri-id`,`edited`), - FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE + INDEX `quote-uri-id` (`quote-uri-id`), + FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, + FOREIGN KEY (`quote-uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Post history'; -- @@ -1436,6 +1440,8 @@ CREATE TABLE IF NOT EXISTS `post-media` ( `embed-html` text COMMENT 'HTML embed code for this media', `embed-height` smallint unsigned COMMENT 'Height of the embed', `embed-width` smallint unsigned COMMENT 'Width of the embed', + `page-type` varchar(30) COMMENT 'Type of the page (e.g. article, website)', + `schematypes` varchar(255) COMMENT 'Schema types of the page as JSON string', `language` char(3) COMMENT 'Language information about this media in the ISO 639 format', `published` datetime COMMENT 'Publification date of this media', `modified` datetime COMMENT 'Modification date of this media', diff --git a/doc/Home.md b/doc/Home.md deleted file mode 100644 index b8b3517a45..0000000000 --- a/doc/Home.md +++ /dev/null @@ -1,82 +0,0 @@ -Help -==== - -**User Manual** - -* General functions - first steps - * [Account Basics](help/Account-Basics) - * [New User Quick Start](help/Quick-Start-guide) - * [Creating posts](help/Text_editor) - * [BBCode tag reference](help/BBCode) - * [Comment, sort and delete posts](help/Text_comment) - * [Accesskey reference](help/Accesskeys) - * [Events](help/events) -* You and other users - * [Connectors](help/Connectors) - * [Making Friends](help/Making-Friends) - * [Safety](help/Safety) - * [Circles and Privacy](help/Circles-and-Privacy) - * [Tags and Mentions](help/Tags-and-Mentions) - * [Community Groups](help/Groups) - * [Channels](help/Channels) - * [Chats](help/Chats) -* Further information - * [Move your account](help/Move-Account) - * [Export / Import of followed Contacts](help/Export-Import-Contacts) - * [Delete your account](help/Remove-Account) - * [Frequently asked questions (FAQ)](help/FAQ) - -**Admin Manual** - -* [Install](help/Install) -* [Update](help/Update) -* [Settings & Admin Panel](help/Settings) -* [Installing Connectors](help/Installing-Connectors) -* [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd) -* [Using SSL with Friendica](help/SSL) -* [Config values that can only be set in config/local.config.php](help/Config) -* [Improve Performance](help/Improve-Performance) -* [Migrate](help/Migrate) -* [Administration Tools](help/tools) -* [Admin FAQ](help/FAQ-admin) - -**Developer Manual** - -* [Get started](help/Developers-Intro) -* Set up development environment - * [Help on GitHub](help/GitHub) - * [Help on Vagrant](help/Vagrant) - * [Bugs and Issues](help/Bugs-and-Issues) -* Code structure - * [Domain-Driven-Design](help/Developer-Domain-Driven-Design) - * [Addon Development](help/Addons) - * [Theme Development](help/themes) - * [Smarty 3 Templates](help/smarty3-templates) - * [Storage backend addon](help/AddonStorageBackend) -* How To - * [Translate Friendica](help/translations) - * [Use Composer](help/Composer) - * [Move classes to `src`](help/Developer-How-To-Move-Classes-to-src) - * [Run tests](help/Tests) -* Reference - * [API endpoints](help/api) - * [Code (Doxygen generated - sets cookies)](doc/html/) - * [Protocol Documentation](help/Protocol) - * [Database schema documentation](help/database) - * [Class Autoloading](help/autoloader) - -**Links** - -* Website: [https://friendi.ca](https://friendi.ca) -* Help Group: [@helpers@forum.friendi.ca](https://forum.friendi.ca/~helpers) -* XMPP: [support@forum.friendi.ca](xmpp:support@forum.friendi.ca?join) -* IRC: [https://web.libera.chat/?channels=#friendica](https://web.libera.chat/?channels=#friendica) -* Matrix: [https://matrix.to/#/#friendi.ca:matrix.org](https://matrix.to/#/#friendi.ca:matrix.org) -* Mailing List: [https://mailman.friendi.ca/mailman/listinfo/support-friendi.ca](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) - - -**About** - -* [Server Information](friendica) -* [Terms of Service](tos) -* [Credits](credits) diff --git a/doc/KeyboardShortcuts.md b/doc/KeyboardShortcuts.md deleted file mode 100644 index cf783b0da1..0000000000 --- a/doc/KeyboardShortcuts.md +++ /dev/null @@ -1,10 +0,0 @@ -Keyboard shortcuts in Friendica -======================= - -* [Home](help) - -General -------- - -* j: Scroll to next thread -* k: Scroll to previous thread diff --git a/doc/Quick-Start-andfinally.md b/doc/Quick-Start-andfinally.md deleted file mode 100644 index 7ea3f5dc72..0000000000 --- a/doc/Quick-Start-andfinally.md +++ /dev/null @@ -1,14 +0,0 @@ -And that brings the Quick Start to an end. - -Here are some more things to help get you started: - -**Groups** - -- Friendica Support - problems? This is the place to ask. - -**Documentation** - -- Connecting to more networks -- Help Index - - diff --git a/doc/Text_comment.md b/doc/Text_comment.md deleted file mode 100644 index 37a91a7dae..0000000000 --- a/doc/Text_comment.md +++ /dev/null @@ -1,32 +0,0 @@ -Comment, sort and delete posts -============== - -* [Home](help) - -Here you can find an overview of the different ways to comment and sort existing posts. Attention: we've used the "diabook" theme. If you're using another theme, some of the icons may be different. - -diabook - -The different icons - -post_thumbs_up.png This symbol is used to indicate that you like the post. Click it twice to undo your choice.

- -post_thumbs_down.png This symbol is used to indicate that you dislike the post. Click it twice to undo your choice. -

- -post_share.png This symbol is used to share a post. A copy of this post will automatically appear in your status editor and add a link to the original post. -

- -post_mark.png This symbol is used to mark a post. Marked posts will appear on your network page at the "starred" tab (from "star"). Click it twice to undo your choice. -

- -post_tag.png This symbol is used to tag a post with a self-chosen keyword. When you click at the word, you'll get a list of all posts with this tag. Attention: you can't delete the tag once you've set one. -

- -post_categorize.png This symbol is used to categorize posts. Choose an existing folder or create a new one. You'll find the created folder on your network page under the "saved folders" tab. -

- -post_delete.png This symbol is used to delete your own post or to remove a post of another person from your stream. -

- -post_choose.png This symbol is used to choose more than one post to delete in a single step. After selecting all posts, go to the end of the page and click "Delete Selected Items".

diff --git a/doc/img/acl_win.png b/doc/assets/img/acl_win.png similarity index 100% rename from doc/img/acl_win.png rename to doc/assets/img/acl_win.png diff --git a/doc/img/camera.png b/doc/assets/img/camera.png similarity index 100% rename from doc/img/camera.png rename to doc/assets/img/camera.png diff --git a/doc/img/chain.png b/doc/assets/img/chain.png similarity index 100% rename from doc/img/chain.png rename to doc/assets/img/chain.png diff --git a/doc/img/diabook.png b/doc/assets/img/diabook.png similarity index 100% rename from doc/img/diabook.png rename to doc/assets/img/diabook.png diff --git a/doc/img/editor_frio.png b/doc/assets/img/editor_frio.png similarity index 100% rename from doc/img/editor_frio.png rename to doc/assets/img/editor_frio.png diff --git a/doc/img/editor_vier.png b/doc/assets/img/editor_vier.png similarity index 100% rename from doc/img/editor_vier.png rename to doc/assets/img/editor_vier.png diff --git a/doc/img/friendica_rich_editor.png b/doc/assets/img/friendica_rich_editor.png similarity index 100% rename from doc/img/friendica_rich_editor.png rename to doc/assets/img/friendica_rich_editor.png diff --git a/doc/img/frio_location.png b/doc/assets/img/frio_location.png similarity index 100% rename from doc/img/frio_location.png rename to doc/assets/img/frio_location.png diff --git a/doc/img/globe.png b/doc/assets/img/globe.png similarity index 100% rename from doc/img/globe.png rename to doc/assets/img/globe.png diff --git a/doc/img/lock.png b/doc/assets/img/lock.png similarity index 100% rename from doc/img/lock.png rename to doc/assets/img/lock.png diff --git a/doc/img/mic.png b/doc/assets/img/mic.png similarity index 100% rename from doc/img/mic.png rename to doc/assets/img/mic.png diff --git a/doc/img/padlock.png b/doc/assets/img/padlock.png similarity index 100% rename from doc/img/padlock.png rename to doc/assets/img/padlock.png diff --git a/doc/img/paper_clip.png b/doc/assets/img/paper_clip.png similarity index 100% rename from doc/img/paper_clip.png rename to doc/assets/img/paper_clip.png diff --git a/doc/img/post_categorize.png b/doc/assets/img/post_categorize.png similarity index 100% rename from doc/img/post_categorize.png rename to doc/assets/img/post_categorize.png diff --git a/doc/img/post_choose.png b/doc/assets/img/post_choose.png similarity index 100% rename from doc/img/post_choose.png rename to doc/assets/img/post_choose.png diff --git a/doc/img/post_delete.png b/doc/assets/img/post_delete.png similarity index 100% rename from doc/img/post_delete.png rename to doc/assets/img/post_delete.png diff --git a/doc/img/post_link.png b/doc/assets/img/post_link.png similarity index 100% rename from doc/img/post_link.png rename to doc/assets/img/post_link.png diff --git a/doc/img/post_mark.png b/doc/assets/img/post_mark.png similarity index 100% rename from doc/img/post_mark.png rename to doc/assets/img/post_mark.png diff --git a/doc/img/post_share.png b/doc/assets/img/post_share.png similarity index 100% rename from doc/img/post_share.png rename to doc/assets/img/post_share.png diff --git a/doc/img/post_tag.png b/doc/assets/img/post_tag.png similarity index 100% rename from doc/img/post_tag.png rename to doc/assets/img/post_tag.png diff --git a/doc/img/post_thumbs_down.png b/doc/assets/img/post_thumbs_down.png similarity index 100% rename from doc/img/post_thumbs_down.png rename to doc/assets/img/post_thumbs_down.png diff --git a/doc/img/post_thumbs_up.png b/doc/assets/img/post_thumbs_up.png similarity index 100% rename from doc/img/post_thumbs_up.png rename to doc/assets/img/post_thumbs_up.png diff --git a/doc/img/posts_define.png b/doc/assets/img/posts_define.png similarity index 100% rename from doc/img/posts_define.png rename to doc/assets/img/posts_define.png diff --git a/doc/img/video.png b/doc/assets/img/video.png similarity index 100% rename from doc/img/video.png rename to doc/assets/img/video.png diff --git a/doc/img/vier_icons.png b/doc/assets/img/vier_icons.png similarity index 100% rename from doc/img/vier_icons.png rename to doc/assets/img/vier_icons.png diff --git a/doc/database.md b/doc/database.md deleted file mode 100644 index 82d900f0ce..0000000000 --- a/doc/database.md +++ /dev/null @@ -1,97 +0,0 @@ -Database Tables -=============== - -* [Home](help) - -| Table | Description | -|-------|-------------| -| [2fa_app_specific_password](help/database/db_2fa_app_specific_password) | Two-factor app-specific _password | -| [2fa_recovery_codes](help/database/db_2fa_recovery_codes) | Two-factor authentication recovery codes | -| [2fa_trusted_browser](help/database/db_2fa_trusted_browser) | Two-factor authentication trusted browsers | -| [account-suggestion](help/database/db_account-suggestion) | Account suggestion | -| [account-user](help/database/db_account-user) | Remote and local accounts | -| [apcontact](help/database/db_apcontact) | ActivityPub compatible contacts - used in the ActivityPub implementation | -| [application](help/database/db_application) | OAuth application | -| [application-marker](help/database/db_application-marker) | Timeline marker | -| [application-token](help/database/db_application-token) | OAuth user token | -| [arrived-activity](help/database/db_arrived-activity) | Id of arrived activities | -| [attach](help/database/db_attach) | file attachments | -| [cache](help/database/db_cache) | Stores temporary data | -| [channel](help/database/db_channel) | User defined Channels | -| [check-full-text-search](help/database/db_check-full-text-search) | Check for a full text search match in user defined channels before storing the message in the system | -| [config](help/database/db_config) | main configuration storage | -| [contact](help/database/db_contact) | contact table | -| [contact-relation](help/database/db_contact-relation) | Contact relations | -| [conv](help/database/db_conv) | private messages | -| [delayed-post](help/database/db_delayed-post) | Posts that are about to be distributed at a later time | -| [delivery-queue](help/database/db_delivery-queue) | Delivery data for posts for the batch processing | -| [diaspora-contact](help/database/db_diaspora-contact) | Diaspora compatible contacts - used in the Diaspora implementation | -| [diaspora-interaction](help/database/db_diaspora-interaction) | Signed Diaspora Interaction | -| [endpoint](help/database/db_endpoint) | ActivityPub endpoints - used in the ActivityPub implementation | -| [event](help/database/db_event) | Events | -| [fetch-entry](help/database/db_fetch-entry) | | -| [fetched-activity](help/database/db_fetched-activity) | Id of fetched activities | -| [fsuggest](help/database/db_fsuggest) | friend suggestion stuff | -| [group](help/database/db_group) | privacy circles, circle info | -| [group_member](help/database/db_group_member) | privacy circles, member info | -| [gserver](help/database/db_gserver) | Global servers | -| [gserver-tag](help/database/db_gserver-tag) | Tags that the server has subscribed | -| [hook](help/database/db_hook) | addon hook registry | -| [inbox-entry](help/database/db_inbox-entry) | Incoming activity | -| [inbox-entry-receiver](help/database/db_inbox-entry-receiver) | Receiver for the incoming activity | -| [inbox-status](help/database/db_inbox-status) | Status of ActivityPub inboxes | -| [intro](help/database/db_intro) | | -| [item-uri](help/database/db_item-uri) | URI and GUID for items | -| [key-value](help/database/db_key-value) | A key value storage | -| [locks](help/database/db_locks) | | -| [mail](help/database/db_mail) | private messages | -| [mailacct](help/database/db_mailacct) | Mail account data for fetching mails | -| [manage](help/database/db_manage) | table of accounts that can manage each other | -| [notification](help/database/db_notification) | notifications | -| [notify](help/database/db_notify) | [Deprecated] User notifications | -| [notify-threads](help/database/db_notify-threads) | | -| [openwebauth-token](help/database/db_openwebauth-token) | Store OpenWebAuth token to verify contacts | -| [parsed_url](help/database/db_parsed_url) | cache for 'parse_url' queries | -| [pconfig](help/database/db_pconfig) | personal (per user) configuration storage | -| [permissionset](help/database/db_permissionset) | | -| [photo](help/database/db_photo) | photo storage | -| [post](help/database/db_post) | Structure for all posts | -| [post-activity](help/database/db_post-activity) | Original remote activity | -| [post-category](help/database/db_post-category) | post relation to categories | -| [post-collection](help/database/db_post-collection) | Collection of posts | -| [post-content](help/database/db_post-content) | Content for all posts | -| [post-counts](help/database/db_post-counts) | Original remote activity | -| [post-delivery](help/database/db_post-delivery) | Delivery data for posts for the batch processing | -| [post-delivery-data](help/database/db_post-delivery-data) | Delivery data for items | -| [post-engagement](help/database/db_post-engagement) | Engagement data per post | -| [post-history](help/database/db_post-history) | Post history | -| [post-link](help/database/db_post-link) | Post related external links | -| [post-media](help/database/db_post-media) | Attached media | -| [post-origin](help/database/db_post-origin) | Posts from local users | -| [post-question](help/database/db_post-question) | Question | -| [post-question-option](help/database/db_post-question-option) | Question option | -| [post-searchindex](help/database/db_post-searchindex) | Content for all posts | -| [post-tag](help/database/db_post-tag) | post relation to tags | -| [post-thread](help/database/db_post-thread) | Thread related data | -| [post-thread-user](help/database/db_post-thread-user) | Thread related data per user | -| [post-user](help/database/db_post-user) | User specific post data | -| [post-user-notification](help/database/db_post-user-notification) | User post notifications | -| [process](help/database/db_process) | Currently running system processes | -| [profile](help/database/db_profile) | user profiles data | -| [profile_field](help/database/db_profile_field) | Custom profile fields | -| [register](help/database/db_register) | registrations requiring admin approval | -| [report](help/database/db_report) | | -| [report-post](help/database/db_report-post) | Individual posts attached to a moderation report | -| [report-rule](help/database/db_report-rule) | Terms of service rule lines relevant to a moderation report | -| [search](help/database/db_search) | | -| [session](help/database/db_session) | web session storage | -| [storage](help/database/db_storage) | Data stored by Database storage backend | -| [subscription](help/database/db_subscription) | Push Subscription for the API | -| [tag](help/database/db_tag) | tags and mentions | -| [user](help/database/db_user) | The local users | -| [user-contact](help/database/db_user-contact) | User specific public contact data | -| [user-gserver](help/database/db_user-gserver) | User settings about remote servers | -| [userd](help/database/db_userd) | Deleted usernames | -| [verb](help/database/db_verb) | Activity Verbs | -| [worker-ipc](help/database/db_worker-ipc) | Inter process communication between the frontend and the worker | -| [workerqueue](help/database/db_workerqueue) | Background tasks queue entries | diff --git a/doc/database/db_conversation.md b/doc/database/db_conversation.md deleted file mode 100644 index 504b0dd4ae..0000000000 --- a/doc/database/db_conversation.md +++ /dev/null @@ -1,30 +0,0 @@ -Table conversation -=========== - -Raw data and structure information for messages - -Fields ------- - -| Field | Description | Type | Null | Key | Default | Extra | -| ----------------- | -------------------------------------------------------------------- | ---------------- | ---- | --- | ------------------- | ----- | -| item-uri | Original URI of the item - unrelated to the table with the same name | varbinary(255) | NO | PRI | NULL | | -| reply-to-uri | URI to which this item is a reply | varbinary(255) | NO | | | | -| conversation-uri | GNU Social conversation URI | varbinary(255) | NO | | | | -| conversation-href | GNU Social conversation link | varbinary(255) | NO | | | | -| protocol | The protocol of the item | tinyint unsigned | NO | | 255 | | -| direction | How the message arrived here: 1=push, 2=pull | tinyint unsigned | NO | | 0 | | -| source | Original source | mediumtext | YES | | NULL | | -| received | Receiving date | datetime | NO | | 0001-01-01 00:00:00 | | - -Indexes ------------- - -| Name | Fields | -| ---------------- | ---------------- | -| PRIMARY | item-uri | -| conversation-uri | conversation-uri | -| received | received | - - -Return to [database documentation](help/database) diff --git a/doc/database/db_host.md b/doc/database/db_host.md deleted file mode 100644 index 4b2d4d1e5d..0000000000 --- a/doc/database/db_host.md +++ /dev/null @@ -1,23 +0,0 @@ -Table host -=========== - -Hostname - -Fields ------- - -| Field | Description | Type | Null | Key | Default | Extra | -| ----- | ------------- | ---------------- | ---- | --- | ------- | -------------- | -| id | sequential ID | tinyint unsigned | NO | PRI | NULL | auto_increment | -| name | The hostname | varchar(128) | NO | | | | - -Indexes ------------- - -| Name | Fields | -| ------- | ------------ | -| PRIMARY | id | -| name | UNIQUE, name | - - -Return to [database documentation](help/database) diff --git a/doc/de/Home.md b/doc/de/Home.md deleted file mode 100644 index 6ea7937ea3..0000000000 --- a/doc/de/Home.md +++ /dev/null @@ -1,76 +0,0 @@ -Hilfe -===== - -**Dokumentation für Benutzer** - -* Allgemeine Funktionen - Erste Schritte - * [Account - Basics](help/Account-Basics) - * [Schnellstart für neue Benutzer](help/Quick-Start-guide) - * [Beiträge erstellen](help/Text_editor) - * [Referenz der BBCode Elemente](help/BBCode) - * [Beiträge kommentieren, einordnen und löschen](help/Text_comment) - * [Referenz der Accesskeys](help/Accesskeys) - * [Veranstaltungen](help/events) -* Du und andere Nutzer - * [Konnektoren (Connectors)](help/Connectors) - * [Freunde finden](help/Making-Friends) - * [Circles und Privatsphäre](help/Circles-and-Privacy) - * [Tags und Erwähnungen](help/Tags-and-Mentions) - * [Community-Gruppen](help/Groups) - * [Kanäle (Channels)](help/Channels) - * [Chats](help/Chats) -* Weiterführende Informationen - * [Account umziehen](help/Move-Account) - * [Export / Import gefolgter Kontakte](help/Export-Import-Contacts) - * [Account löschen](help/Remove-Account) - * [Bugs und Probleme](help/Bugs-and-Issues) - * [Häufig gestellte Fragen (FAQ)](help/FAQ) - -**Dokumentation für Administratoren** - -* [Installation](help/Install) -* [Update](help/Update) (EN) -* [Konfigurationen & Admin-Panel](help/Settings) -* [Addons](help/Addons) -* [Konnektoren (Connectors) installieren](help/Installing-Connectors) -* [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/install-ejabberd) (EN) -* [Betreibe deine Seite mit einem SSL-Zertifikat](help/SSL) -* [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können](help/Config) (EN) -* [Performance verbessern](help/Improve-Performance) -* [Administration Werkzeuge](help/tools) (EN) -* [Admin FAQ](help/FAQ-admin) - -**Dokumentation für Entwickler** - -* [Entwickler](help/Developers) -* [Where to get started?](help/Developers-Intro) (EN) -* [Help on Github](help/Github) -* [Help on Vagrant](help/Vagrant) -* [How to translate Friendica](help/translations) (EN) -* [Bugs and Issues](help/Bugs-and-Issues) -* [Addon Development](help/Addons) -* [Theme Development](help/themes) -* [Smarty 3 Templates](help/smarty3-templates) -* [Protokoll Dokumentation](help/Protocol) (EN) -* [Datenbank-Schema](help/database) -* [Class Autoloading](help/autoloader) (EN) -* [Using Composer](help/Composer) (EN) -* [Code-Referenz (mit doxygen generiert - setzt Cookies)](doc/html/) -* [API Dokumentation](help/api) (EN) -* [Translation of Friendica](help/translations) (EN) -* [Run tests](help/Tests) (EN) - -**Links** - -* Website: [https://friendi.ca](https://friendi.ca) -* Help Group: [@helpers@forum.friendi.ca](https://forum.friendi.ca/~helpers) -* XMPP: [support@forum.friendi.ca](xmpp:support@forum.friendi.ca?join) -* IRC: [https://web.libera.chat/?channels=#friendica](https://web.libera.chat/?channels=#friendica) -* Matrix: [https://matrix.to/#/#friendi.ca:matrix.org](https://matrix.to/#/#friendi.ca:matrix.org) -* Mailing List: [https://mailman.friendi.ca/mailman/listinfo/support-friendi.ca](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) - -**Über** - -* [Server Information](friendica) -* [Nutzungsbedingungen](tos) -* [Mitwirkende](credits) diff --git a/doc/de/Quick-Start-andfinally.md b/doc/de/Quick-Start-andfinally.md deleted file mode 100644 index 748f600deb..0000000000 --- a/doc/de/Quick-Start-andfinally.md +++ /dev/null @@ -1,18 +0,0 @@ -... und zuletzt -=============== - -Und damit sind wir auch schon am Ende der Schnellstartanleitung. - -Hier sind noch einige weitere Dinge, die Dir den Start vereinfachen können. - -**Gruppen** - - -- Friendica Support - Probleme? Dann ist das der Platz, um zu fragen! - -**Dokumentation** - -- Zu weiteren Netzwerken verbinden -- Zur Startseite der Hilfe - - diff --git a/doc/de/Text_editor.md b/doc/de/Text_editor.md deleted file mode 100644 index 4c71ae559d..0000000000 --- a/doc/de/Text_editor.md +++ /dev/null @@ -1,51 +0,0 @@ -Beiträge erstellen -================= - -* [Zur Startseite der Hilfe](help) - -Hier findest du eine Übersicht über die verschiedenen Möglichkeiten, deinen Beitrag zu bearbeiten. - -Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. -Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht oder in anderer Form vorfinden. - - -editor - -Die einzelnen Symbole - -editor Wenn du auf dieses Symbol klickst, dann kannst du ein Bild von deinem Computer hinzufügen. -Wenn du eine Internetadresse (URL) eingeben willst, dann kannst du das "Baum"-Symbol im oberen Teil des Editors nutzen. -Wenn du ein Bild ausgewählt hast, dann erscheint eine Miniaturdarstellung des Bildes im Editor.* -

- -paper_clip Wenn du dieses Symbol anklickst, dann kannst du weitere Dateien von deinem Computer einfügen. Eine Vorschau des Dateiinhalts erfolgt nicht.* -

- -chain Wenn du die Kette anklickst, dann kannst du eine Internetadresse (URL) einfügen. -Im Editor erscheint automatisch eine kurze Information zum eingefügten Link.* -

- -video Mit dieser Funktion kannst du die Internetadresse (URL) einer Videodatei einfügen. -Das Video erscheint dann mit einem Player in deinem Beitrag. -Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser verschiedene Videoformate unterstützt (z.B. WebM oder MP4). -Außerdem kannst du hier die URLs von Videos auf Youtube, Vimeo und manchen anderen Videohostern eingeben. -Die Videos werden dann mit Vorschaubild angezeigt, nach einem Klick öffnet sich ein eingebetteter Player.* -

- -mic Mit dieser Funktion kannst du die Internetadresse (URL) einer Sound-Datei einfügen. -Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser und Betriebssystem MP3, Ogg oder AAC unterstützt. -Außerdem kannst du hier auch URLs von manchen Audiohostern wie Soundcloud eingeben, um eine dort gespeicherte Audiodatei mit Player in deinem Beitrag anzuzeigen.* -

- -globe Wenn du dieses Symbol wählst, dann kannst du deinen Standort festlegen. -Hier reicht schon eine Angabe wie "Berlin" oder "10775". -Dieser Eintrag führt anschließend zu einer Suchanfrage bei Google Maps. -

- -* wie du Dateien hochladen kannst, erfährst du [hier](help/FAQ#upload) - -**Im Folgenden findest du Symbole weiterer Themen** - -Frio frio.png - -Vier vier.png diff --git a/doc/de/FAQ-admin.md b/doc/de/admin/faq.md similarity index 62% rename from doc/de/FAQ-admin.md rename to doc/de/admin/faq.md index 3b171afe51..7d1ee251ef 100644 --- a/doc/de/FAQ-admin.md +++ b/doc/de/admin/faq.md @@ -1,25 +1,13 @@ -Häufig gestellte Fragen (Admin) - FAQ -============== +# Häufig gestellte Fragen (Admin) - FAQ -* [Zur Startseite der Hilfe](help) - -* **[Kann ich mehrere Domains mit den selben Dateien aufsetzen?](help/FAQ-admin#multiple)** -* **[Wo kann ich den Quellcode von Friendica, Addons und Themes finden?](help/FAQ-admin#sources)** -* **[Ich habe meine E-Mail Adresse geändern und jetzt ist das Admin Panel verschwunden?](help/FAQ-admin#adminaccount1)** -* **[Kann es mehr als einen Admin auf einer Friendica Instanz geben?](help/FAQ-admin#adminaccount2)** -* **[Die Datenbank Struktur schein nicht aktuell zu sein. Was kann ich tun?](help/FAQ-admin#dbupdate)** - - - -### Kann ich mehrere Domains mit den selben Dateien aufsetzen? +## Kann ich mehrere Domains mit den selben Dateien aufsetzen? Ja, das ist möglich. Es ist allerdings nicht möglich, eine Datenbank durch zwei Domains zu nutzen. Solange Du Deine config/local.config.php allerdings so einrichtest, dass das System nicht versucht, eine Installation durchzuführen, kannst Du die richtige Config-Datei in include/$hostname/config/local.config.php hinterlegen. Alle Cache-Aspekte und der Zugriffsschutz können pro Instanz konfiguriert werden. - -### Wo kann ich den Quellcode von Friendica, Addons und Themes finden? +## Wo kann ich den Quellcode von Friendica, Addons und Themes finden? Du kannst den Friendica-Quellcode [hier](https://github.com/friendica/friendica) finden. Dort findest Du immer die aktuellste stabile Version von Friendica. @@ -29,13 +17,11 @@ Addons findest Du auf [dieser Seite](https://github.com/friendica/friendica-addo Wenn Du neue Themen suchst, findest Du sie auf [github.com/bkil/friendica-themes](https://github.com/bkil/friendica-themes). - -### Ich habe meine E-Mail Adresse geändern und jetzt ist das Admin Panel verschwunden? +## Ich habe meine E-Mail Adresse geändern und jetzt ist das Admin Panel verschwunden? Bitte aktualisiere deine E-Mail Adresse in der config/local.config.php Datei. - -### Kann es mehr als einen Admin auf einer Friendica Instanz geben? +## Kann es mehr als einen Admin auf einer Friendica Instanz geben? Ja. Du kannst in der config/local.config.php Datei mehrere E-Mail Adressen auflisten. @@ -45,8 +31,7 @@ Die aufgelisteten Adressen werden wie folgt durch Kommas voneinander getrennt: 'admin_email' => 'mail1@example.com,mail2@example.com', ``` - -### Die Datenbank Struktur schein nicht aktuell zu sein. Was kann ich tun? +## Die Datenbank Struktur schein nicht aktuell zu sein. Was kann ich tun? Rufe bitte im Admin Panel den Punkt [DB Updates](/admin/dbsync/) auf und folge dem Link *Datenbank Struktur überprüfen*. Damit wird ein Hintergrundprozess gestartet der die Struktur deiner Datenbank überprüft und gegebenenfalls aktualisiert. diff --git a/doc/de/Improve-Performance.md b/doc/de/admin/improve-performance.md similarity index 84% rename from doc/de/Improve-Performance.md rename to doc/de/admin/improve-performance.md index df90437e74..a33ce5892b 100644 --- a/doc/de/Improve-Performance.md +++ b/doc/de/admin/improve-performance.md @@ -1,7 +1,4 @@ -How-to: Performance verbessern -========== - -* [Zur Startseite der Hilfe](help) +# How-to: Performance verbessern Eine kleine Anleitung, um die Performance einer Friendica-Seite zu verbessern. @@ -9,27 +6,25 @@ Eine kleine Anleitung, um die Performance einer Friendica-Seite zu verbessern. Wenn du Fragen zu den folgenden Anweisungen oder zu anderen Themen hast, dann kannst du jederzeit beim Friendica-Support unter https://forum.friendi.ca/profile/helpers nachfragen. -Systemeinstellungen ---------------- +## Systemeinstellungen -Geh auf /admin/site in deinem System und ändere die folgenden Werte: +Geh auf `/admin/site` in deinem System und ändere die folgenden Werte: setze "Qualität des JPEG Bildes" auf 50. -Dieser Wert reduziert die Daten, die vom Server an den Client geschickt werden. +Dieser Wert reduziert die Daten, die vom Server an den Client geschickt werden. 50 ist ein Wert, der die Bildqualität nicht zu stark beeinflusst. setze "Intervall zum Vervollständigen von OStatus Unterhaltungen" auf "niemals" -Wenn du viele OStatus-Kontakte hast, dann kann die Vervollständigung von Unterhaltungen sehr zeitraubend sein. +Wenn du viele OStatus-Kontakte hast, dann kann die Vervollständigung von Unterhaltungen sehr zeitraubend sein. Der Nachteil: Du siehst nicht jede Antwort einer OStatus-Unterhaltung. Aus diesem Grund ist die Option "Beim Empfang von Nachrichten" in der Regel ein guter Kompromiss. setze "Nutze MySQL full text engine". Wenn du MyISAM (Standardeinstellung) oder InnoDB mit MariaDB 10 nutzt, dann beschleunigt dies die Suche. -Addons --------- +## Addons Aktiviere die folgenden Addons: @@ -55,8 +50,7 @@ Wenn es aktiviert ist, dann siehst du Werte wie die folgenden auf jeder deiner S Diese Werte zeigen deine Performance-Probleme. -Webserver ----------- +## Webserver Wenn du einen Apache-Webserver nutzt, aktiviere bitte die folgenden Module: @@ -80,7 +74,7 @@ Weitere Informationen findest du hier: http://httpd.apache.org/docs/2.2/mod/mod_ Dieses Modul komprimiert den Datenverkehr (Traffic) zwischen dem Webserver und dem Client. -Aktiviere das Modul "mod_deflate" durch die Eingabe "a2enmod deflate" als root. +Aktiviere das Modul `mod_deflate` durch die Eingabe `a2enmod deflate` als root. Weitere Informationen findest du hier: http://httpd.apache.org/docs/2.2/mod/mod_deflate.html @@ -89,9 +83,9 @@ Weitere Informationen findest du hier: http://httpd.apache.org/docs/2.2/mod/mod_ **FCGI** -Wenn du Apache nutzt, dann denk darüber nach, FCGI zu nutzen. +Wenn du Apache nutzt, dann denk darüber nach, FCGI zu nutzen. Wenn du eine Debian-basierte Distribution nutzt, dann wirst du die Pakete "php5-cgi" und "libapache2-mod-fcgid" benötigen. -Nutze externe Dokumente, um eine detailiertere Erklärung für die Einrichtung eines Systems auf FCGI-Basis zu erhalten. +Nutze externe Dokumente, um eine detailliertere Erklärung für die Einrichtung eines Systems auf FCGI-Basis zu erhalten. ### Database diff --git a/doc/de/Install.md b/doc/de/admin/install.md similarity index 78% rename from doc/de/Install.md rename to doc/de/admin/install.md index 205127e34e..a5d9c5fb74 100644 --- a/doc/de/Install.md +++ b/doc/de/admin/install.md @@ -1,9 +1,6 @@ -Friendica Installation -========== +# Friendica Installation -* [Zur Startseite der Hilfe](help) - -Wir haben hart daran gearbeitet, um Friendica auf vorgefertigten Hosting-Plattformen zum Laufen zu bringen - solche, auf denen auch Wordpress Blogs und Drupal-Installationen laufen. +Wir haben hart daran gearbeitet, um Friendica auf vorgefertigten Hosting-Plattformen zum Laufen zu bringen - solche, auf denen auch WordPress Blogs und Drupal-Installationen laufen. Wir bieten eine manuelle und eine automatische Installation an. Aber bedenke, dass Friendica mehr als eine einfache Webanwendung ist. Es handelt sich um ein komplexes Kommunikationssystem, das eher an einen Email-Server erinnert als an einen Webserver. @@ -12,7 +9,7 @@ Diese Funktionalität benötigt ein wenig mehr als die normalen Blogs. Nicht jeder PHP/MySQL-Hosting-Anbieter kann Friendica unterstützen. Viele hingegen können es. Aber **bitte** prüfe die Voraussetzungen deines Servers vor der Installation. -Wenn dir Fehler während der Installation auffallen, sag uns bitte über [Helper](http://forum.friendi.ca/profile/helpers) oder die [Entwickler Gruppe](https://forum.friendi.ca/profile/developers) Bescheid oder [erstelle ein Issue](https://github.com/friendica/friendica/issues). +Wenn dir Fehler während der Installation auffallen, sag uns bitte über [Helper](https://forum.friendi.ca/profile/helpers) oder die [Entwickler Gruppe](https://forum.friendi.ca/profile/developers) Bescheid oder [erstelle ein Issue](https://github.com/friendica/friendica/issues). Gib uns bitte so viele Infos zu deinem System, wie du kannst, und beschreibe den Fehler mit allen Details und Fehlermeldungen, so dass wir den Fehler zukünftig verhindern können. Aufgrund der großen Anzahl an verschiedenen Betriebssystemen und PHP-Plattformen haben wir nur geringe Kapazitäten, um deine PHP-Installation zu debuggen oder fehlende Module zu ersetzen, aber wir tun unser Bestes, um allgemeine Code-Fehler zu beheben. @@ -21,10 +18,9 @@ Dinge verändern sich und einige deiner Freunde haben möglicherweise Probleme, Wir planen, diese Einschränkung in einer zukünftigen Version zu beheben. -Requirements ---- +## Requirements -* Apache mit einer aktiverten mod-rewrite-Funktion und dem Eintrag "Options All", so dass du die lokale .htaccess-Datei nutzen kannst +* Apache mit einer aktiverten mod-rewrite-Funktion und dem Eintrag "Options All", so dass du die lokale `.htaccess`-Datei nutzen kannst * PHP 7.4+ * PHP *Kommandozeilen*-Zugang mit register_argc_argv auf "true" gesetzt in der php.ini-Datei * Curl, GD, GMP, PDO, mbstrings, MySQLi, hash, xml, zip, IntlChar, IDN und OpenSSL-Erweiterung @@ -35,8 +31,7 @@ Requirements * die Möglichkeit, wiederkehrende Aufgaben mit cron (Linux/Mac) oder "Scheduled Tasks" einzustellen (Windows) [Beachte: andere Optionen sind in Abschnitt 7 dieser Dokumentation zu finden] * Installation in einer Top-Level-Domain oder Subdomain (ohne eine Verzeichnis/Pfad-Komponente in der URL) wird bevorzugt. Verzeichnispfade sind für diesen Zweck nicht so günstig und wurden auch nicht ausführlich getestet. -Installation ---- +## Installation ### Alternative Wege um Friendica zu Installieren @@ -56,38 +51,44 @@ Entpacke die Friendica-Daten in das Quellverzeichnis (root) des Dokumentenbereic Wenn du die Möglichkeit hierzu hast, empfehlen wir dir "git" zu nutzen, um die Daten direkt von der Quelle zu klonen, statt die gepackte .tar- oder .zip-Datei zu nutzen. Das macht die Aktualisierung wesentlich einfacher. Der Linux-Code, mit dem man die Dateien direkt in ein Verzeichnis wie "meinewebseite" kopiert, ist - - git clone https://github.com/friendica/friendica.git -b stable mywebsite - cd mywebsite - bin/composer.phar run install:prod +```sh +git clone https://github.com/friendica/friendica.git -b stable mywebsite +cd mywebsite +bin/composer.phar run install:prod +``` Stelle sicher, dass der Ordner *view/smarty3* existiert and von dem Webserver-Benutzer beschreibbar ist - - mkdir view/smarty3 - chmod 775 view/smarty3 +```sh +mkdir view/smarty3 +chmod 775 view/smarty3 +``` Falls Addons installiert werden sollen: Gehe in den Friendica-Ordner - - cd mywebsite +```sh +cd mywebsite +``` Und die Addon Repository klonst: - - git clone https://github.com/friendica/friendica-addons.git -b stable addon +```sh +git clone https://github.com/friendica/friendica-addons.git -b stable addon +``` Um das Addon-Verzeichnis aktuell zu halten, solltest du in diesem Pfad ein "git pull"-Befehl eintragen +```sh +cd meinewebseite/addon +git pull +``` - cd meinewebseite/addon - git pull - -Wenn du den Verzeichnispfad auf deinen Webserver kopierst, dann stelle sicher, dass du auch die .htaccess kopierst, da "Punkt"-Dateien oft versteckt sind und normalerweise nicht direkt kopiert werden. +Wenn du den Verzeichnispfad auf deinen Webserver kopierst, dann stelle sicher, dass du auch die `.htaccess` kopierst, da "Punkt"-Dateien oft versteckt sind und normalerweise nicht direkt kopiert werden. Wenn du die Entwickler Version von Friendica verwenden möchtest kannst du auf den develop Branch im git Repository wechseln. Dies tust du mit den folgenden Befehlen - - git checkout develop - bin/composer.phar run install:prod - cd addon - git checkout develop +```sh +git checkout develop +bin/composer.phar run install:prod +cd addon +git checkout develop +``` Die Entwickler Version kann nach einem fehlerhaften Commit vorübergehend Probleme haben oder gar nicht mehr funktionieren. Sollte dir so etwas passieren, lass es uns bitte wissen, damit der Fehler behoben werden kann. @@ -101,8 +102,9 @@ Friendica benötigt die Berechtigungen um neue Felder in dieser Datenbank zu ert Mit neueren Versionen von MySQL (5.7.17+) musst du den `sql_mode` zu `''` (blank) setzen. Benutze diese Einstellung, wenn der Installer nicht in der Lage ist, die Tabellen aufgrund eines Timestamp-Format Problems zu erstellen. Falls dem so ist, finde den `[mysqld]` Bereich in deiner `my.conf` Datei und füge diese Zeile hinzu: - - sql_mode = '' +``` +sql_mode = '' +``` Starte MySQL dann neu und es sollte klappen. @@ -126,39 +128,42 @@ Du kannst bei Bedarf die Datei config/local.config.php verschieben/umbenennen un ### Option B: Starte das automatische Installationsscript Es existieren folgende Varianten zur automatischen Installation von Friendica: -- Eine vorgefertigte Konfigurationsdatei erstellen (z.B. `prepared.config.php`) -- Verwendung von Umgebungsvariablen (z.B. `MYSQL_HOST`) -- Verwendung von Optionen (z.B. `--dbhost `) +- Eine vorgefertigte Konfigurationsdatei erstellen (z.B. `prepared.config.php`) +- Verwendung von Umgebungsvariablen (z.B. `MYSQL_HOST`) +- Verwendung von Optionen (z.B. `--dbhost `) Umgebungsvariablen und Optionen können auch kombiniert werden. Dabei ist jedoch darauf zu achten, dass etwaige Optionen immer die zugehörigen Umgebungsvariablen überschreiben. Für mehr Informationen kannst du diese Option verwenden: - - bin/console autoinstall -v +```sh +bin/console autoinstall -v +``` Falls du alle optionalen Checks ausfürehn lassen möchtest, benutze diese Option: - - bin/console autoinstall -a +```sh +bin/console autoinstall -a +``` *Wenn* die automatisierte Installation aus irgendeinem Grund fehlschlägt, dann prüfe das Folgende: -* Existiert die `config/local.config.php`? Falls ja, wird die automatisierte Installation nicht gestartet. -* Sind Einstellungen in der `config/local.config.php` korrekt? Falls nicht, bitte bearbeite diese Datei erneut. -* Ist die leere MySQL-Datenbank erstellt? Falls nicht, erstelle diese. +* Existiert die `config/local.config.php`? Falls ja, wird die automatisierte Installation nicht gestartet. +* Sind Einstellungen in der `config/local.config.php` korrekt? Falls nicht, bitte bearbeite diese Datei erneut. +* Ist die leere MySQL-Datenbank erstellt? Falls nicht, erstelle diese. #### B.1: Konfigurationsdatei Für diese Variante muss ein Konfigurationsdatei bereits vor der Installation fertig definiert sein (z.B. [local-sample.config.php](config/local-sample.config.php). Gehe im Anschluss in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus: - - bin/console autoinstall -f +```sh +bin/console autoinstall -f +``` #### B.2: Umgebungsvariablen Es existieren Zwei Arten von Umgebungsvariablen in Friendica: -- Jene, die auch im normalen Betrieb verwendet werden können (derzeit ausschließlich **Datenbank Einstellungen**) -- Jene, die nur während der Installation verwedent werden können (im normalen Betrieb werden sie ignoriert) +- Jene, die auch im normalen Betrieb verwendet werden können (derzeit ausschließlich **Datenbank Einstellungen**) +- Jene, die nur während der Installation verwedent werden können (im normalen Betrieb werden sie ignoriert) Umgebungsvariablen können auch durch adäquate Optionen (z.B. `--dbhost `)übersteuert werden. @@ -166,57 +171,62 @@ Umgebungsvariablen können auch durch adäquate Optionen (z.B. `--dbhost ` Der Host der MySQL/MariaDB Datenbank (env `MYSQL_HOST`) -- `-p|--dbport ` Der Port der MySQL/MariaDB Datenbank (env `MYSQL_PORT`) -- `-U|--dbuser ` Der Benutzername des MySQL/MariaDB Datenbanklogins (env `MYSQL_USER` or `MYSQL_USERNAME`) -- `-P|--dbpass ` Das Passwort der MySQL/MariaDB Datenbanklogins (env `MYSQL_PASSWORD`) -- `-d|--dbdata ` Der Name der MySQL/MariaDB Datenbank (env `MYSQL_DATABASE`) -- `-b|--phppath ` Der Pfad zur PHP-Datei (env `FRIENDICA_PHP_PATH`) -- `-A|--admin ` Die Admin E-Mail Adresse dieses Friendica Knotens (env `FRIENDICA_ADMIN_MAIL`) -- `-T|--tz ` Die Zeitzone von Friendica (env `FRIENDICA_TZ`) -- `-L|--lang ` Die Sprache von Friendica (env `FRIENDICA_LANG`) +- `-H|--dbhost ` Der Host der MySQL/MariaDB Datenbank (env `MYSQL_HOST`) +- `-p|--dbport ` Der Port der MySQL/MariaDB Datenbank (env `MYSQL_PORT`) +- `-U|--dbuser ` Der Benutzername des MySQL/MariaDB Datenbanklogins (env `MYSQL_USER` or `MYSQL_USERNAME`) +- `-P|--dbpass ` Das Passwort der MySQL/MariaDB Datenbanklogins (env `MYSQL_PASSWORD`) +- `-d|--dbdata ` Der Name der MySQL/MariaDB Datenbank (env `MYSQL_DATABASE`) +- `-b|--phppath ` Der Pfad zur PHP-Datei (env `FRIENDICA_PHP_PATH`) +- `-A|--admin ` Die Admin E-Mail Adresse dieses Friendica Knotens (env `FRIENDICA_ADMIN_MAIL`) +- `-T|--tz ` Die Zeitzone von Friendica (env `FRIENDICA_TZ`) +- `-L|--lang ` Die Sprache von Friendica (env `FRIENDICA_LANG`) Gehe in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus: - - bin/console autoinstall [options] +```sh +bin/console autoinstall [options] +``` ### Einen Worker einrichten Erstelle einen Cron job oder einen regelmäßigen Task, um den Poller alle 5-10 Minuten im Hintergrund ablaufen zu lassen. Beispiel: - - cd /base/directory; /path/to/php bin/console.php worker +```sh +cd /base/directory; /path/to/php bin/console.php worker +``` Ändere "/base/directory" und "/path/to/php" auf deine Systemvorgaben. Wenn du einen Linux-Server nutzt, benutze den Befehl "crontab -e" und ergänze eine Zeile wie die Folgende; angepasst an dein System -`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker` +```crontab +*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker +``` Du kannst den PHP-Pfad finden, indem du den Befehl „which php“ ausführst. Wenn du Schwierigkeiten mit diesem Schritt hast, kannst du deinen Hosting-Anbieter kontaktieren. diff --git a/doc/de/Installing-Connectors.md b/doc/de/admin/installing-connectors.md similarity index 93% rename from doc/de/Installing-Connectors.md rename to doc/de/admin/installing-connectors.md index 7d378e2374..d196d6892b 100644 --- a/doc/de/Installing-Connectors.md +++ b/doc/de/admin/installing-connectors.md @@ -1,7 +1,4 @@ -Konnektoren installieren -================================================== - -* [Zur Startseite der Hilfe](help) +# Konnektoren installieren Friendica verwendet Konnektoren, um sich mit einigen Netzwerken zu verbinden, wie Tumblr oder Bluesky. @@ -19,8 +16,7 @@ Andere Konnektoren, wie Bluesky, 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 ---- +## Bluesky 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. diff --git a/doc/de/Settings.md b/doc/de/admin/settings.md similarity index 95% rename from doc/de/Settings.md rename to doc/de/admin/settings.md index cee965ccaf..239c07bd7d 100644 --- a/doc/de/Settings.md +++ b/doc/de/admin/settings.md @@ -1,7 +1,5 @@ # Settings -* [Zur Startseite der Hilfe](help) - Wenn du der Administrator einer Friendica-Instanz bist, hast du Zugriff auf das so genannte **Admin Panel** in dem du die Friendica-Instanz konfigurieren kannst, Auf der Startseite des Admin Panels werden die Informationen zu der Instanz zusammengefasst. @@ -41,16 +39,15 @@ Sie wird verwendet, wenn es Friendica nicht gelingt die Spracheinstellungen des Nutzer können diese Auswahl in den Einstellungen des Benutzerkontos überschreiben. Die Friendica Gemeinschaft bietet einige Übersetzungen an, von denen einige mehr andere weniger komplett sind. -Mehr Informationen zum Übersetzungsprozess von Friendica findest du [auf dieser Seite](/help/translations) der Dokumentation. +Mehr Informationen zum Übersetzungsprozess von Friendica findest du [auf dieser Seite](/help/developer/translations) der Dokumentation. #### Systemweites Theme Hier kann das Theme bestimmt werden, welches standardmäßig zum Anzeigen der Seite verwendet werden soll. Nutzer können in ihren Einstellungen andere Themes wählen. -Derzeit ist das "vier" Theme das vorausgewählte Theme. +Derzeit ist das "frio" Theme das vorausgewählte Theme. Für mobile Geräte kannst du ein spezielles Theme wählen, wenn das Standardtheme ungeeignet für mobile Geräte sein sollte. -Das `vier` Theme z.B. unterstützt kleine Anzeigen und benötigt kein zusätzliches mobiles Theme. ### Registrierung @@ -66,7 +63,7 @@ Dabei kannst du zwischen den folgenden Optionen wählen: ##### Einladungen Zusätzlich zu den oben genannten Möglichkeiten, kann die Registrierung eines neuen Nutzerkontos an eine Einladung durch einen bestehenden Nutzer gekoppelt werden. -Hierzu muss in der [config/local.config.php](/help/Config) Datei die Option `invitation_only` aktiviert und als Registrierungsmethode entweder *Offen* oder *Bedarf der Zustimmung* gewählt werden. +Hierzu muss in der [config/local.config.php](/help/admin/config) Datei die Option `invitation_only` aktiviert und als Registrierungsmethode entweder *Offen* oder *Bedarf der Zustimmung* gewählt werden. #### Namen auf Vollständigkeit überprüfen @@ -106,7 +103,7 @@ Falls ein solches verwendet wird, sei an dieser Stelle nur auf deren Dokumentati Die Grundeinstellung ist 'Datenbank (legacy)': Dies ist die alte Methode von Friendica Daten direkt in der Datenbank abzulegen. Bestehende Daten können zum aktuell ausgewählten Backend verschoben werden. -Hierfür kann der ['storage move'](help/tools) Befehl der Friendica Konsole verwendet werden. +Hierfür kann der ['storage move'](help/admin/tools) Befehl der Friendica Konsole verwendet werden. Sollte das ausgewählte Speicher Backand zusätzliche Konfigurationsparameter besitzen, werden nach der Auswahl des Backends hier weitere Felder angezeigt. @@ -335,10 +332,12 @@ Du solltest deshalb einen Dienst zur [log rotation](https://en.wikipedia.org/wik Normalerweise werden Fehler- und Warnmeldungen von PHP unterdrückt. Wenn du sie aktivieren willst, musst du folgendes in der `config/local.config.php` Datei eintragen um die Meldungen in die Datei `php.out` zu speichern - error_reporting(E_ERROR | E_WARNING | E_PARSE ); - ini_set('error_log','php.out'); - ini_set('log_errors','1'); - ini_set('display_errors', '0'); +``` +error_reporting(E_ERROR | E_WARNING | E_PARSE ); +ini_set('error_log','php.out'); +ini_set('log_errors','1'); +ini_set('display_errors', '0'); +``` Die Datei `php.out` muss vom Webserver schreibbar sein und sollte ebenfalls außerhalb der Webverzeichnisse liegen. Es kommt gelegentlich vor, dass nicht deklarierte Variablen referenziert werden, dehalb raten wir davon ab `E_NOTICE` oder `E_ALL` zu verwenden. @@ -367,13 +366,15 @@ Dies sind die Datenbank Einstellungen, die Administrator Accounts, der PHP Pfad Mit den folgenden Einstellungen kannst du die Zugriffsdaten für den Datenbank Server festlegen. - 'database' => [ - 'hostname' => 'localhost', - 'username' => 'mysqlusername', - 'password' => 'mysqlpassword', - 'database' => 'mysqldatabasename', - 'charset' => 'utf8mb4', - ], +``` +'database' => [ + 'hostname' => 'localhost', + 'username' => 'mysqlusername', + 'password' => 'mysqlpassword', + 'database' => 'mysqldatabasename', + 'charset' => 'utf8mb4', +], +``` Sollten alle der folgenden Environment-Variablen gesetzt sein, wird Friendica diese anstatt der vorher konfigurierten Werte nutzen. @@ -390,18 +391,22 @@ Normalerweise trifft dies auf den ersten Account zu, der nach der Installation a Die Liste der E-Mail Adressen kann aber einfach erweitert werden. Mit keiner der angegebenen E-Mail Adressen können weitere Accounts registriert werden. - 'config' => [ - 'admin_email' => 'you@example.com, buddy@example.com', - ], +``` +'config' => [ + 'admin_email' => 'you@example.com, buddy@example.com', +], +``` ## PHP Pfad Einige Prozesse von Friendica laufen im Hintergrund. Für diese Prozesse muss der Pfad zu der PHP Version gesetzt sein, die verwendet werden soll. - 'config' => [ - 'php_path' => '/usr/bin/php', - ], +``` +'config' => [ + 'php_path' => '/usr/bin/php', +], +``` ## Unterverzeichnis Konfiguration @@ -409,11 +414,13 @@ Man kann Friendica in ein Unterverzeichnis des Webservers installieren. Wir raten allerdings dringen davon ab, da es die Interoperabilität mit anderen Netzwerken (z.B. Diaspora, GNU Social, Hubzilla) verhindert. Mal angenommen, du hast ein Unterverzeichnis tests und willst Friendica in ein weiteres Unterverzeichnis installieren, dann lautet die Konfiguration hierfür: - 'system' => [ - 'url' => 'https://example.com/tests/friendica', - ], +``` +'system' => [ + 'url' => 'https://example.com/tests/friendica', +], +``` ## Weitere Ausnahmen Es gibt noch einige experimentelle Einstellungen, die nur in der ``config/local.config.php`` Datei konfiguriert werden können. -Im [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können (EN)](help/Config) Artikel kannst du mehr darüber erfahren. +Im [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können (EN)](help/admin/config) Artikel kannst du mehr darüber erfahren. diff --git a/doc/de/SSL.md b/doc/de/admin/ssl.md similarity index 82% rename from doc/de/SSL.md rename to doc/de/admin/ssl.md index 3d20cb5b1e..0584e1dbe0 100644 --- a/doc/de/SSL.md +++ b/doc/de/admin/ssl.md @@ -1,7 +1,4 @@ -Friendica mit SSL nutzen -===================================== - -* [Zur Startseite der Hilfe](help) +# Friendica mit SSL nutzen ## Disclaimer @@ -47,9 +44,9 @@ Wenn ja, dann lies weiter. Wenn du einen eigenen Server betreibst und den Nameserver kontrollierst, könnte auch die Initiative "Let's encrypt" interessant für dich werden. Sie bietet nicht nur freie SSL Zertifikate sondern auch einen automatisierten Prozess zum Erneuern der Zertifikate. -Um letsencrypt Zertifikate verwenden zu können, musst du dir einen Client auf deinem Server installieren. -Eine Anleitung zum offiziellen Client findet du [hier](https://certbot.eff.org/). -Falls du dir andere Clients anschauen willst, kannst du einen Blick in diese [Liste von alternativen letsencrypt Clients](https://letsencrypt.org/docs/client-options/). +Um LetsEncrypt Zertifikate verwenden zu können, musst du dir einen Client auf deinem Server installieren. +Eine Anleitung zum offiziellen Client findest du [hier](https://certbot.eff.org/). +Falls du dir andere Clients anschauen willst, kannst du einen Blick in diese [Liste von alternativen LetsEncrypt Clients](https://letsencrypt.org/docs/client-options/). ## Webserver-Einstellungen @@ -62,32 +59,37 @@ Wenn du fertig bist, kannst du auf der Testseite [SSL-Labs](https://www.ssllabs. ## Friendica Konfigurieren -Wenn du deine Friendica Instanz über https erreichen kannst solltest du ein paar Einstellungen vornehmen um sicher zu stellen, dass deine Nutzer ausschließlich über https zugreifen können. +Wenn du deine Friendica Instanz über https erreichen kannst solltest du ein paar Einstellungen vornehmen um sicherzustellen, dass deine Nutzer ausschließlich über https zugreifen können. ### Webserver-Umleitungen Dies ist der einfachste Weg den Zugriff für die ganze Webseite abzusichern. -Jedes Mal wenn ein Nutzer Friendica aufruft wird er permanent vom Webserver auf die abgesicherte Seite umgeleitet. +Jedes Mal, wenn ein Nutzer Friendica aufruft wird er permanent vom Webserver auf die abgesicherte Seite umgeleitet. Wenn du den Apache Webserver verwendest, aktiviere die Module rewrite und ssl (bei einem Shared-Hosting Prider sollte dies bereits der Fall sein): - sudo a2enmod rewrite ssl +```sh +sudo a2enmod rewrite ssl +``` -und füge die folgenden Zeilen zur .htaccess Datei im Wurzelverzeichnis deiner Friendica Instanz hinzu: +und füge die folgenden Zeilen zur `.htaccess` Datei im Wurzelverzeichnis deiner Friendica Instanz hinzu: - RewriteEngine On - RewriteCond %{SERVER_PORT} 80 - RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] +``` +RewriteEngine On +RewriteCond %{SERVER_PORT} 80 +RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] +``` (Dank an [url=https://github.com/AlfredSK]AlfredSK[/url]). Bei nginx solltest du deinen Server folgendermaßen konfigurieren ([documentation](https://www.nginx.com/blog/creating-nginx-rewrite-rules/)): - - server { - listen 80; - server_name your.friendica.domain; - return 301 https://$server_name$request_uri; - } +``` +server { + listen 80; + server_name your.friendica.domain; + return 301 https://$server_name$request_uri; +} +``` ### SSL Einstellungen diff --git a/doc/de/Addons.md b/doc/de/developer/addon-development.md similarity index 98% rename from doc/de/Addons.md rename to doc/de/developer/addon-development.md index 5f42a53c2a..b774da6984 100644 --- a/doc/de/Addons.md +++ b/doc/de/developer/addon-development.md @@ -1,7 +1,4 @@ -Friendica Addon/Entwicklung -============== - -* [Zur Startseite der Hilfe](help) +# Friendica Addon/Entwicklung Bitte schau dir das Beispiel-Addon "randplace" für ein funktionierendes Beispiel für manche der hier aufgeführten Funktionen an. Das Facebook-Addon bietet ein Beispiel dafür, die "addon"- und "module"-Funktion gemeinsam zu integrieren. @@ -28,15 +25,14 @@ Registriere deine Addon-Hooks während der Installation. \Friendica\Core\Hook::register($hookname, $file, $function); -$hookname ist ein String und entspricht einem bekannten Friendica-Hook. +`$hookname` ist ein String und entspricht einem bekannten Friendica-Hook. -$file steht für den Pfadnamen, der relativ zum Top-Level-Friendicaverzeichnis liegt. -Das *sollte* "addon/addon_name/addon_name.php' sein. +$file steht für den Pfadnamen, der relativ zum Top-Level-Friendica-Verzeichnis liegt. +Das *sollte* `addon/addon_name/addon_name.php` sein. $function ist ein String und der Name der Funktion, die ausgeführt wird, wenn der Hook aufgerufen wird. -Argumente ---- +## Argumente Deine Hook-Callback-Funktion wird mit höchstens einem Argumenten aufgerufen @@ -51,8 +47,7 @@ Diese Information ist speziell auf den Hook bezogen, der aktuell bearbeitet wird Achte darauf, diese mit "&" zu deklarieren, wenn du sie bearbeiten willst. -Module ---- +## Module Addons können auch als "Module" agieren und alle Seitenanfragen für eine bestimte URL abfangen. Um ein Addon als Modul zu nutzen, ist es nötig, die Funktion "addon_name_module()" zu definieren, die keine Argumente benötigt und nichts weiter machen muss. @@ -72,8 +67,7 @@ Sie können auch `addon_name_post()` umfassen, welches vor der content-Funktion Du kannst ebenso `addon_name_init()` nutzen, was oft frühzeitig aufgerufen wird und das Modul initialisert. -Derzeitige Hooks ---- +## Derzeitige Hooks **'authenticate'** - wird aufgerufen, wenn sich der User einloggt. $b ist ein Array @@ -189,8 +183,7 @@ Dieser Hook kann dafür verwendet werden, alternative Erkennungsfunktionen einzu - wird aufgerufen nachdem in include/nav,php der Inhalt des Navigations Menüs erzeugt wurde. - $b ist ein Array, das $nav wiederspiegelt. -Komplette Liste der Hook-Callbacks ---- +## Komplette Liste der Hook-Callbacks Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Apr-2018 generiert): Bitte schau in die Quellcodes für Details zu Hooks, die oben nicht dokumentiert sind. diff --git a/doc/de/Developers.md b/doc/de/developer/guide.md similarity index 86% rename from doc/de/Developers.md rename to doc/de/developer/guide.md index 4c5e4a62b9..4284d5376d 100644 --- a/doc/de/Developers.md +++ b/doc/de/developer/guide.md @@ -1,7 +1,4 @@ -Friendica - Entwickler-Guide -========== - -* [Zur Startseite der Hilfe](help) +# Friendica - Entwickler-Guide Hier erfährst Du, wie Du bei uns mitmachen kannst: @@ -9,19 +6,19 @@ Zunächst erstelle Dir per 'git clone https://github.com/friendica/friendica.git Erstelle Deine eigene Kopie (fork) der Ursprungsdaten auf Github, an der Du dann entspannt arbeiten kannst. Deine Arbeiten sollten mit einem neuen Arbeitszweig (branch) beginnen, den du vom develop Zweig des Repositories beginnst. -Die Anleitung unter [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/) erklärt Dir genau, wie Du das tun musst. +Die Anleitung unter [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/) erklärt dir genau, wie du das tun musst. Gehe dann nach getaner Arbeit zu Deiner Github-Seite und erstelle eine "Pull request", um Deine Änderungen in das Hauptprojekt einzugliedern (merge). -Solltest du keine Idee haben, an welcher Stelle du einsteigen könntest. +Solltest du keine Idee haben, an welcher Stelle du einsteigen könntest? Wir haben einige Aufgaben auf github mit dem Schlagwort *Junior Job* versehen. Bei diesen Aufgaben gehen wir davon aus, dass sie geeignete Einstiegsstellen sind. -Du musst dich aber natürlich nicht mit diesen Aufgaben beschäftigen um den Friendica Code zu verbeesern. +Du musst dich aber natürlich nicht mit diesen Aufgaben beschäftigen um den Friendica Code zu verbessern. **Wichtig** Bitte hole Dir alle Änderungen aus dem Projektverzeichnis und führe sie mit Deiner Arbeit zusammen, **bevor** Du Deine "pull request" erstellst. Wir behalten es uns vor, Patches abzulehnen, die eine große Anzahl an Fehlern hervorrufen. -Dies gilt vor allem für Übersetzungen, da wir hier möglicherweise nicht alle feinen Unterschiede in konfliktären Versionen erkennen können. +Dies gilt vor allem für Übersetzungen, da wir hier möglicherweise nicht alle feinen Unterschiede in konfliktähren Versionen erkennen können. Außerdem: **teste Deine Änderungen!** Vergiss nicht, dass eine simple Fehlerlösung einen anderen Fehler auslösen kann. Lass Deine Änderungen von einem erfahrenen Friendica-Entwickler gegenprüfen. diff --git a/doc/de/guide.md b/doc/de/guide.md deleted file mode 100644 index fde9cb8ea4..0000000000 --- a/doc/de/guide.md +++ /dev/null @@ -1,26 +0,0 @@ -Erste Schritte... -========== - -* [Zur Startseite der Hilfe](help) - -Das Erste zum Anfang: geh sicher, dass du schon eingeloggt bist. -Wenn du noch nicht eingeloggt bist, kannst du das in dem Fenster unten machen. - -Sobald du eingeloggt bist (oder wenn du bereits eingeloggt bist), kannst du unten nun auf deine Profilseite schauen. - -Hier sieht es ein wenig wie auf deiner Facebook-Seite aus. -Hier findest du alle deine Statusmeldungen und Nachrichten deiner Freunde, die direkt auf deine Seite ("Wall") geschrieben haben. -Um deinen Status einzutragen, klicke einfach auf die Box oben, in der "Teilen" steht. -Wenn du das machst, vergrößert sich die Box. -Nun kannst du einige Formatierungsoptionen wie Fett, kursiv, unterstrichen auswählen und ebenfalls Bilder und Links hinzufügen. -Unten findest du in diesem Feld weitere Links, mit denen du Bilder und Dateien von deinem Computer hochladen, Webseiten mit einem Kurztext teilen und Video- und Audiodateien aus dem Internet einfügen kannst. -Außerdem kannst du hier eintragen, wo du gerade bist. - -Wenn du deinen Beitrag ("Post") geschrieben hast, kannst du auf das "Schloss"-Symbol klicken und festlegen, wer deinen Beitrag sehen kann. -Wenn du dieses Symbol nicht anklickst, ist dein Beitrag öffentlich. -Das bedeutet, dass jeder, der dein Profil ansieht, der auf dem "Community"-Tab deines Servers oder auf dem "Netzwerk"-Tab ("Beiträge deiner Kontakte") eines befreundeten Kontakts ist, den Beitrag sehen kann. - -Probiere es doch einfach mal aus. Wenn du fertg bist, schauen wir uns den "Netzwerk"-Tab an. - - - diff --git a/doc/de/home.md b/doc/de/home.md new file mode 100644 index 0000000000..138ad3777b --- /dev/null +++ b/doc/de/home.md @@ -0,0 +1,72 @@ +# Hilfe + +## Dokumentation für Benutzer + +* Allgemeine Funktionen - Erste Schritte + * [Account - Basics](help/user/account-basics) + * [Schnellstart für neue Benutzer](help/user/quick-start/guide) + * [Beiträge erstellen](help/user/text-editor) + * [Referenz der BBCode Elemente](help/user/bbcode) + * [Beiträge kommentieren, einordnen und löschen](help/user/text-comment) + * [Referenz der Accesskeys](help/user/access-keys) (EN) + * [Veranstaltungen](help/user/events) + * [Themes](help/user/themes) (EN) +* Du und andere Nutzer + * [Konnektoren (Connectors)](help/user/connectors) + * [Freunde finden](help/user/making-friends) + * [Circles und Privatsphäre](help/user/circles-and-privacy) + * [Tags und Erwähnungen](help/user/tags-and-mentions) + * [Accountypen: Gruppen und Seiten](help/user/accounts-groups-pages) + * [Kanäle (Channels)](help/user/channels) + * [Chats](help/user/chats) +* Weiterführende Informationen + * [Häufig gestellte Fragen (FAQ)](help/user/faq) + * [Account umziehen](help/user/move-account) + * [Export / Import gefolgter Kontakte](help/user/export-import-contacts) + * [Account löschen](help/user/delete-account) + * [Bugs und Probleme](help/user/bugs-and-issues) + +## Dokumentation für Administratoren + +* [Installation](help/admin/install) +* [Update](help/admin/update) (EN) +* [Häufig gestellte Fragen FAQ](help/admin/faq) +* [Konfigurationen & Admin-Panel](help/admin/settings) +* [Konnektoren (Connectors) installieren](help/admin/installing-connectors) +* [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/admin/install-ejabberd) (EN) +* [Betreibe deine Seite mit einem SSL-Zertifikat](help/admin/ssl) +* [Konfigurationswerte, die nur in der config/local.config.php gesetzt werden können](help/admin/config) (EN) +* [Performance verbessern](help/admin/improve-performance) +* [Administration Werkzeuge](help/admin/tools) (EN) + +## Dokumentation für Entwickler + +* [Guide](help/developer/guide) +* [Where to get started?](help/developer/index) (EN) +* [On GitHub](help/developer/github) (EN) +* [On Vagrant](help/developer/vagrant) (EN) +* [Translate Friendica](help/developer/translations) (EN) +* [Addon Development](help/developer/addon-development) +* [Smarty 3 Templates](help/developer/smarty3-templates) (EN) +* [Protokoll Dokumentation](help/spec/protocol/protocol) (EN) +* [Datenbank-Schema](help/spec/database/index) (EN) +* [Class Autoloading](help/developer/autoloader) (EN) +* [Using Composer](help/developer/composer) (EN) +* [Code-Referenz (mit doxygen generiert - setzt Cookies)](doc/html/) +* [API Dokumentation](help/spec/api/index) (EN) +* [Run tests](help/developer/tests) (EN) + +## Links + +* Website: [https://friendi.ca](https://friendi.ca) +* Help Group: [@helpers@forum.friendi.ca](https://forum.friendi.ca/~helpers) +* XMPP: [support@forum.friendi.ca](xmpp:support@forum.friendi.ca?join) +* IRC: [https://web.libera.chat/?channels=#friendica](https://web.libera.chat/?channels=#friendica) +* Matrix: [https://matrix.to/#/#friendi.ca:matrix.org](https://matrix.to/#/#friendi.ca:matrix.org) +* Mailing List: [https://mailman.friendi.ca/mailman/listinfo/support-friendi.ca](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) + +## Über + +* [Server Information](friendica) +* [Nutzungsbedingungen](tos) +* [Mitwirkende](credits) diff --git a/doc/de/README.md b/doc/de/readme.md similarity index 83% rename from doc/de/README.md rename to doc/de/readme.md index a4e2bdec77..08fa5d79d8 100644 --- a/doc/de/README.md +++ b/doc/de/readme.md @@ -1,9 +1,8 @@ -Friendica-doc-german -==================== +# Friendica-doc-german Friendica - doc - german -Hier findest du die deutsche Version der Friendica-Hilfedateien. -Es handelt sich um eine selbst erstellte, öffentlich freigegebene Arbeit mit dem Ziel, Friendica durch deutsche Hilfedateien für weitere Personen zugänglich zu machen, die dem Englischen nicht ausreichend mächtig sind. +Hier findest du die deutsche Version der Friendica-Hilfedateien. +Es handelt sich um eine selbst erstellte, öffentlich freigegebene Arbeit mit dem Ziel, Friendica durch deutsche Hilfedateien für weitere Personen zugänglich zu machen, die dem Englischen nicht ausreichend mächtig sind. Die Daten basieren auf dem offiziellen Friendica-Github https://github.com/friendica/friendica (Stand: 03.11.12) diff --git a/doc/de/Message-Flow.md b/doc/de/spec/protocol/message-flow.md similarity index 77% rename from doc/de/Message-Flow.md rename to doc/de/spec/protocol/message-flow.md index ef2a0a2715..14ba78265c 100644 --- a/doc/de/Message-Flow.md +++ b/doc/de/spec/protocol/message-flow.md @@ -1,14 +1,11 @@ -Friendica Nachrichtenfluss -============== +# Friendica Nachrichtenfluss -* [Zur Startseite der Hilfe](help) - -Diese Seite soll einige Infos darüber dokumentieren, wie Nachrichten innerhalb von Friendica von einer Person zur anderen übertragen werden. -Es gibt verschiedene Pfade, die verschiedene Protokolle und Nachrichtenformate nutzen. +Diese Seite soll einige Infos darüber dokumentieren, wie Nachrichten innerhalb von Friendica von einer Person zur anderen übertragen werden. +Es gibt verschiedene Pfade, die verschiedene Protokolle und Nachrichtenformate nutzen. Diejenigen, die den Nachrichtenfluss genauer verstehen wollen, sollten sich mindestens mit dem DFRN-Protokoll ([Dokument mit den DFRN Spezifikationen](https://github.com/friendica/friendica/blob/stable/spec/dfrn2.pdf)) und den Elementen zur Nachrichtenverarbeitung des OStatus Stack informieren (salmon und Pubsubhubbub). -Wenn eine Nachricht veröffentlicht wird, werden alle Übermittlungen an alle Netzwerke mit include/notifier.php durchgeführt, welche entscheidet, wie und an wen die Nachricht geliefert wird. +Wenn eine Nachricht veröffentlicht wird, werden alle Übermittlungen an alle Netzwerke mit include/notifier.php durchgeführt, welche entscheidet, wie und an wen die Nachricht geliefert wird. Diese Datei bindet dabei die lokale Bearbeitung aller Übertragungen ein inkl. dfrn-notify. mod/dfrn_notify.php handhabt die Rückmeldung (remote side) von dfrn-notify. @@ -22,40 +19,40 @@ PuSh-Feeds (pubsubhubbub) kommen via mod/pubsub.php an. DFRN-poll Feed-Imports kommen via src/Worker/OnePoll.php als geplanter Task an, das implementiert die lokale Bearbeitung (local side) des DFRN-Protokolls. -### Szenario #1. Bob schreibt eine öffentliche Statusnachricht +## Szenario #1. Bob schreibt eine öffentliche Statusnachricht -Dies ist eine öffentliche Nachricht ohne begrenzte Nutzerfreigabe, so dass keine private Übertragung notwendig ist. -Es gibt zwei Wege, die genutzt werden können - als bbcode an DFRN-Clients oder als durch den Server konvertierten HTML-Code (mit PuSH; pubsubhubbub). -Wenn ein PuSH-Hub einsatzfähig ist, nutzen DFRN-Poll-Clients vorrangig die Informationen, die durch den PuSH-Kanal kommen. -Sie fallen zurück auf eine tägliche Abfrage, wenn der Hub Übertragungsschwierigkeiten hat (das kann vorkommen, wenn der standardmäßige Google-Referenzhub genutzt wird). -Wenn kein spezifizierter Hub oder Hubs ausgewählt sind, werden DFRN-Clients in einer pro Kontakt konfigurierbaren Rate mit bis zu 5-Minuten-Intervallen abfragen. +Dies ist eine öffentliche Nachricht ohne begrenzte Nutzerfreigabe, so dass keine private Übertragung notwendig ist. +Es gibt zwei Wege, die genutzt werden können - als bbcode an DFRN-Clients oder als durch den Server konvertierten HTML-Code (mit PuSH; pubsubhubbub). +Wenn ein PuSH-Hub einsatzfähig ist, nutzen DFRN-Poll-Clients vorrangig die Informationen, die durch den PuSH-Kanal kommen. +Sie fallen zurück auf eine tägliche Abfrage, wenn der Hub Übertragungsschwierigkeiten hat (das kann vorkommen, wenn der standardmäßige Google-Referenzhub genutzt wird). +Wenn kein spezifizierter Hub oder Hubs ausgewählt sind, werden DFRN-Clients in einer pro Kontakt konfigurierbaren Rate mit bis zu 5-Minuten-Intervallen abfragen. Feeds, die via DFRN-Poll abgerufen werden, sind bbcode und können auch private Unterhaltungen enthalten, die vom Poller auf ihre Zugriffsrechte hin geprüft werden. -### Szenario #2. Jack antwortet auf Bobs öffentliche Nachricht. Jack ist im Friendica/DFRN-Netzwerk. +## Szenario #2. Jack antwortet auf Bobs öffentliche Nachricht. Jack ist im Friendica/DFRN-Netzwerk. -Jack nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. -Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist und dfrn-notify nutzt. +Jack nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. +Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist und dfrn-notify nutzt. Die PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen diese an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können). -### Szenario #3. Mary antwortet auf Bobs öffentliche Nachricht. Mary ist im Friendica/DFRN-Netzwerk. +## Szenario #3. Mary antwortet auf Bobs öffentliche Nachricht. Mary ist im Friendica/DFRN-Netzwerk. -Mary nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. -Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist (mit Ausnahme von Bob selbst; die Unterhaltung wird nun an Jack und Mary geschickt). -Die Nachrichten werden mit dfrn-notify übertragen. -PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. +Mary nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. +Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist (mit Ausnahme von Bob selbst; die Unterhaltung wird nun an Jack und Mary geschickt). +Die Nachrichten werden mit dfrn-notify übertragen. +PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen sie an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können). -### Szenario #4. William antwortet auf Bobs öffentliche Nachricht. William ist in einem OStatus-Netzwerk. +## Szenario #4. William antwortet auf Bobs öffentliche Nachricht. William ist in einem OStatus-Netzwerk. -William nutzt salmon, um Bob über seine Antwort zu benachrichtigen. -Der Inhalt ist HTML-Code, der in das Salmon Magic Envelope eingebettet ist. -Bob erstellt dann einen Feed der Unterhaltung und sendet es an alle Friendica-Nutzer, die an der Unterhaltung beteiligt sind und dfrn-notify nutzen (mit Ausnahme von William selbst; die Unterhaltung wird an Jack und Mary weitergeleitet). +William nutzt salmon, um Bob über seine Antwort zu benachrichtigen. +Der Inhalt ist HTML-Code, der in das Salmon Magic Envelope eingebettet ist. +Bob erstellt dann einen Feed der Unterhaltung und sendet es an alle Friendica-Nutzer, die an der Unterhaltung beteiligt sind und dfrn-notify nutzen (mit Ausnahme von William selbst; die Unterhaltung wird an Jack und Mary weitergeleitet). PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen sie an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können). -### Szenario #5. Bob schreibt eine private Nachricht an Mary und Jack. +## Szenario #5. Bob schreibt eine private Nachricht an Mary und Jack. -Die Nachricht wird sofort an Mary und Jack mit Hilfe von dfrn_notify geschickt. -Öffentliche Hubs werden nicht benachrichtigt. -Im Falle eines Timeouts wird eine erneute Verarbeitung angestoßen. -Antworten folgen dem gleichen Nachrichtenfluss wie öffentliche Antworten, allerdings werden die Hubs nicht darüber informiert, wodurch die Nachrichten niemals in öffentliche Feeds gelangen. +Die Nachricht wird sofort an Mary und Jack mithilfe von dfrn_notify geschickt. +Öffentliche Hubs werden nicht benachrichtigt. +Im Falle eines Timeouts wird eine erneute Verarbeitung angestoßen. +Antworten folgen dem gleichen Nachrichtenfluss wie öffentliche Antworten, allerdings werden die Hubs nicht darüber informiert, wodurch die Nachrichten niemals in öffentliche Feeds gelangen. Die komplette Unterhaltung ist nur für Mary und Jack in ihren durch dfrn-poll personalisierten Feeds verfügbar (und für niemanden sonst). diff --git a/doc/de/Account-Basics.md b/doc/de/user/account-basics.md similarity index 87% rename from doc/de/Account-Basics.md rename to doc/de/user/account-basics.md index ef7ca4e63f..13cb5d352a 100644 --- a/doc/de/Account-Basics.md +++ b/doc/de/user/account-basics.md @@ -1,8 +1,4 @@ -Account - Basics -============== - -* [Zur Startseite der Hilfe](help) - +# Account - Basics ## Registrierung @@ -19,15 +15,12 @@ Falls du keine [OpenID-Adresse](https://de.wikipedia.org/wiki/OpenID">OpenID-Adr Solltest du eine OpenID Adresse haben, kannst Du sie im ersten Feld eintragen und "Registrieren" klicken. Friendica wird versuchen, so viele Informationen wie möglich von Deinem OpenID-Provider zu übernehmen, um diese in Dein Profil auf dieser Seite einzutragen. - ### Dein vollständiger Name Bitte trage bei "vollständiger Name" Deinen **gewünschten Namen** ein, wie er über deinen Beiträgen angezeigt werden soll. -Du kannst deinen echten Namen eintragen, kannst Dir aber auch einen Namen ausdenken. Einen Zwang zu dem sogenannten Klarnamen gibt es nicht. +Du kannst deinen echten Namen eintragen, kannst dir aber auch einen Namen ausdenken. Einen Zwang zu dem sogenannten Klarnamen gibt es nicht. - - -### Email-Adresse +### E-Mail-Adresse Bitte trage eine richtige Email-Adresse ein. Dies ist die einzige persönliche Information, die korrekt sein muss. @@ -51,45 +44,40 @@ Durch die Art, wie der Spitzname genutzt wird, gibt es bestimmte Einschränkunge Dieser Spitzname wird an vielen Stellen genutzt, um Deinen Account zu identifizieren, daher ist es nicht möglich ihn später zu ändern. - ### Verzeichnis-Eintrag Das Registrierungsformular erlaubt es dir, direkt auszuwählen, ob Du im [Onlineverzeichnis](https://dir.friendica.social/) (Friendica Directory) aufgelistet wirst oder nicht. -Das ist wie ein Telefonbuch und Du entscheidest, ob du darin eingetragen werden möchtest, oder nicht. +Das ist wie ein Telefonbuch und du entscheidest, ob du darin eingetragen werden möchtest, oder nicht. -* Wir bitten dich, "Ja" zu wählen, damit Andere Dich finden können, so wie Du sie finden kannst +* Wir bitten dich, "Ja" zu wählen, damit Andere dich finden können, so wie Du sie finden kannst * Wählst Du "Nein", bist Du für Andere *nicht einfach auffindbar* Was auch immer Du wählst, kann jederzeit nach dem Login in Deinen Account-Einstellungen geändert werden. - ### Registrierung Sobald Du die nötigen Informationen eingegeben hast, klicke auf "Registrieren". Eine Email mit den Registrierungsdetails und Deinem Initialpasswort wird an die hinterlegte Email-Adresse geschickt. -Bitte prüfe den Posteingang (inkl. dem Spam-Ordner). - +Bitte prüfe den Posteingang (inklusive dem Spam-Ordner). ## Login-Seite Gib auf der "Login"-Seite die Informationen ein, die Du mit der oben genannten Email erhalten hast. Du kannst entweder Deinen Spitznamen oder die Email-Adresse als Login-Namen nutzen. -Wenn Du Deinen Account nutzt, um unterschiedliche '[Seiten](help/Pages)' zu verwalten, die die gleiche Email-Adresse verwenden, dann nutze bitte den Spitznamen des Accounts, der verwaltet werden soll. +Wenn Du Deinen Account nutzt, um unterschiedliche '[accounts (Gruppen/Seiten)](help/accounts-groups-pages)' zu verwalten, die die gleiche Email-Adresse verwenden, dann nutze bitte den Spitznamen des Accounts, der verwaltet werden soll. *Wenn* Dein Account OpenID nutzt, dann kannst Du Deine OpenID-Adresse als Login-Name nutzen und das Passwort-Feld frei lassen. -Du wirst zu Deinem OpenID-Anbieter weitergeleitet, wo Du Deine Anmeldung abschließt. +Du wirst zu deinem OpenID-Anbieter weitergeleitet, wo Du Deine Anmeldung abschließt. Wenn Du OpenID nicht nutzt, dann gib Dein Passwort ein, das Du mit der Registrierungsmail erhalten hast. Das Passwort muss genau so geschrieben werden, wie es in der Email steht; Groß- und Kleinschreibung wird beachtet. Falls Du Schwierigkeiten beim Login hast, prüfe bitte, ob z. B. Deine Feststelltaste aktiv ist. - ### Passwort ändern Besuche nach Deinem ersten Login bitte die Einstellungsseite und wechsle das Passwort in eines, dass Du Dir merken kannst. - ## Die ersten Schritte ### Persönliche Daten exportieren @@ -106,17 +94,14 @@ Dies ist z.B. dann nützlich wenn du mit deinem Account auf einen anderen Friend Ein ['Tipp für neue Mitglieder'](newmember)-Link zeigt sich in den ersten beiden Wochen auf Deiner Startseite, um Dir erste Informationen zum Start zu bieten. - ## Schau Dir ebenfalls folgende Seiten an -* [Circles und Privatssphäre](help/Circles-and-Privacy) +* [Circles und Privatssphäre](help/user/circles-and-privacy) -* [Account löschen](help/Remove-Account) +* [Account löschen](help/user/delete-account) ### Der eigene Friendica-Knoten + Wenn Du Deinen eigenen Friendica-Knoten auf einem Server aufsetzen willst, kannst Du das ebenfalls machen. Besuche die [Friendica-Webseite](https://friendi.ca), um den Code mit den Installationsanleitungen herunterzuladen. Es ist ein einfacher Installationsprozess, den jeder mit ein wenig technischen Erfahrungen im Webseiten-Hosting oder mit grundlegenden Linux-Erfahrungen handhaben kann. - - - diff --git a/doc/de/Groups.md b/doc/de/user/accounts-groups-pages.md similarity index 98% rename from doc/de/Groups.md rename to doc/de/user/accounts-groups-pages.md index 52455cfa7f..7a955aa38f 100644 --- a/doc/de/Groups.md +++ b/doc/de/user/accounts-groups-pages.md @@ -1,8 +1,4 @@ -Gruppen -===== - -* [Zur Startseite der Hilfe](help) - +# Accounttypen: Gruppen und Seiten In Friendica kannst Du auch Gruppen und/oder Prominenten-Seiten erstellen. diff --git a/doc/de/BBCode.md b/doc/de/user/bbcode.md similarity index 84% rename from doc/de/BBCode.md rename to doc/de/user/bbcode.md index 2057d40c55..c2e35ba427 100644 --- a/doc/de/BBCode.md +++ b/doc/de/user/bbcode.md @@ -1,7 +1,4 @@ -Referenz der Friendica BBCode Tags -======================== - -* [Zur Startseite der Hilfe](help) +# Referenz der Friendica BBCode Tags ## Inline @@ -61,8 +58,8 @@ table.bbcodes > * > tr > th { rot - [url=http://friendi.ca]Friendica[/url] - Friendica + [url=https://friendi.ca]Friendica[/url] + Friendica [img]https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.png[/img] @@ -103,23 +100,23 @@ table.bbcodes > * > tr > th { Ergebnis - [url]http://friendi.ca[/url] - http://friendi.ca + [url]https://friendi.ca[/url] + https://friendi.ca - [url=http://friendi.ca.com]Friendica[/url] - Friendica + [url=https://friendi.ca.com]Friendica[/url] + Friendica - [bookmark]http://friendi.ca[/bookmark]

-#^[url]http://friendi.ca[/url] -

Friendica: http://friendi.ca

+ [bookmark]https://friendi.ca[/bookmark]

+#^[url]https://friendi.ca[/url] +

Friendica: https://friendi.ca

- [bookmark=http://friendi.ca]Lesezeichen[/bookmark]

-#^[url=http://friendi.ca]Lesezeichen[/url]

-#[url=http://friendi.ca]^[/url][url=http://friendi.ca]Lesezeichen[/url] -

Friendica: Lesezeichen

+ [bookmark=https://friendi.ca]Lesezeichen[/bookmark]

+#^[url=https://friendi.ca]Lesezeichen[/url]

+#[url=https://friendi.ca]^[/url][url=https://friendi.ca]Lesezeichen[/url] +

Friendica: Lesezeichen

[url=/posts/f16d77b0630f0134740c0cc47a0ea02a]Diaspora Beitrag mit GUID[/url] @@ -171,7 +168,7 @@ Zeilen [code=php]function text_highlight($s,$lang)[/code] -
  1.  function text_highlight($s,$lang)
+
  1. function text_highlight($s,$lang)
[quote]Zitat[/quote] @@ -255,21 +252,21 @@ Zeilen [table]
-  [tr]
-    [th]Kopfzeile 1[/th]
-    [th]Kopfzeile 2[/th]
-    [th]Kopfzeile 2[/th]
-  [/tr]
-  [tr]
-    [td]Zelle 1[/td]
-    [td]Zelle 2[/td]
-    [td]Zelle 3[/td]
-  [/tr]
-  [tr]
-    [td]Zelle 4[/td]
-    [td]Zelle 5[/td]
-    [td]Zelle 6[/td]
-  [/tr]
+ [tr]
+ [th]Kopfzeile 1[/th]
+ [th]Kopfzeile 2[/th]
+ [th]Kopfzeile 2[/th]
+ [/tr]
+ [tr]
+ [td]Zelle 1[/td]
+ [td]Zelle 2[/td]
+ [td]Zelle 3[/td]
+ [/tr]
+ [tr]
+ [td]Zelle 4[/td]
+ [td]Zelle 5[/td]
+ [td]Zelle 6[/td]
+ [/tr]
[/table] @@ -352,12 +349,12 @@ Zeilen
[ul]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/ul]
[list]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/list]
    @@ -368,12 +365,12 @@ Zeilen
[ol]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/ol]
[list=1]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/list]
    @@ -384,8 +381,8 @@ Zeilen
[list=]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/list]
    @@ -396,8 +393,8 @@ Zeilen
[list=i]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/list]
    @@ -408,8 +405,8 @@ Zeilen
[list=I]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/list]
    @@ -420,8 +417,8 @@ Zeilen
[list=a]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/list]
    @@ -432,8 +429,8 @@ Zeilen
[list=A]
-  [li] Erstes Listenelement
-  [li] Zweites Listenelement
+ [li] Erstes Listenelement
+ [li] Zweites Listenelement
[/list]
    @@ -551,7 +548,7 @@ Als ich die Bilder im Wald aufgenommen habe, hatte ich eine wirklich ungewö
-Für Verbindungen zu Netzwerken, zu denen Friendica den HTML Code postet, wie Tumblr, Wordpress oder Pump.io wird das [abstract] Element nicht verwendet. +Für Verbindungen zu Netzwerken, zu denen Friendica den HTML Code postet, wie Tumblr, WordPress oder Pump.io wird das [abstract] Element nicht verwendet. Bei nativen Verbindungen; das heißt zu z.B. Friendica, Hubzilla, Diaspora oder GNU Social Kontakten; wird der ungekürzte Beitrag übertragen. Die Instanz des Kontakts kümmert sich um die Darstellung. @@ -595,4 +592,3 @@ Du kannst alle [style=text-shadow: 0 0 4px #CC0000;]CSS-Eigenschaften[/style] di Du kannst alle CSS-Eigenschaften dieses Inline-Textes ändern- - diff --git a/doc/de/Bugs-and-Issues.md b/doc/de/user/bugs-and-issues.md similarity index 69% rename from doc/de/Bugs-and-Issues.md rename to doc/de/user/bugs-and-issues.md index 4db1bd6aa3..3e543a1b8a 100644 --- a/doc/de/Bugs-and-Issues.md +++ b/doc/de/user/bugs-and-issues.md @@ -1,16 +1,13 @@ -Bugs und Probleme -=============== +# Bugs und Probleme -* [Zur Startseite der Hilfe](help) - -Du solltest jeden Bug und jedes Problem, den/das Du findest, zunächst dem Administrator (oder gegebenenfalls der Support-Seite) Deines Servers melden, statt auf der allgemeinen Bug-Seite. +Du solltest jeden Bug und jedes Problem, den/das Du findest, zunächst dem Administrator (oder gegebenenfalls der Support-Seite) Deines Servers melden, statt auf der allgemeinen Bug-Seite. Das erleichtert den Entwicklern ihre Arbeit (z. B. neue Features zu entwickeln), da sie sich nicht mit Fehlern beschäftigen müssen, mit denen sie nichts zu tun haben. -Wenn Du technisch versiert bist oder Dein Knoten keine Support-Seite hat, dann kannst Du den Bug Tracker nutzen. -Bitte durchsuche zunächst die Seite, ob es bereits einen offenen Bug gibt, der Deiner Anfrage entspricht. +Wenn Du technisch versiert bist oder Dein Knoten keine Support-Seite hat, dann kannst Du den Bug Tracker nutzen. +Bitte durchsuche zunächst die Seite, ob es bereits einen offenen Bug gibt, der Deiner Anfrage entspricht. -Liefere so viele Informationen wie möglich zu dem Bug. -Hierzu gehört auch die **komplette** Fehlermeldung oder Notiz und alle Schritte, die zu dem Fehler geführt haben. -Es ist generell besser, zu viele Informationen zu liefern, als zu wenige. +Liefere so viele Informationen wie möglich zu dem Bug. +Hierzu gehört auch die **komplette** Fehlermeldung oder Notiz und alle Schritte, die zu dem Fehler geführt haben. +Es ist generell besser, zu viele Informationen zu liefern, als zu wenige. Lies Dir diesen Artikel (mehrsprachig) durch, um mehr über **gute** Bug-Reports zu erfahren. diff --git a/doc/de/Channels.md b/doc/de/user/channels.md similarity index 98% rename from doc/de/Channels.md rename to doc/de/user/channels.md index 686fd129b1..6a6e63be19 100644 --- a/doc/de/Channels.md +++ b/doc/de/user/channels.md @@ -1,7 +1,4 @@ -Kanäle (Channels) -===== - -* [Home](help) +# Kanäle (Channels) Kanäle sind eine Möglichkeit neue Inhalte zu finden, oder Inhalte anzuzeigen, die du sonst möglicherweise verpasst hättest. Es gibt mehrere vordefinierte Kanäle und zusätzlich kannst du deine eigenen, basierend auf ein paar Regeln, erstellen. @@ -18,8 +15,7 @@ Auf der Profilseite kannst du die Kanal-Frequenz für jeden Kontakt definieren. * Zeige nur einige Beiträge an: Wenn ein Kontakt viele Beiträge in einem kurzen Zeitraum erstellt, reduziert diese Einstellung die Anzahl der angezeigten Beiträge in jedem Kanal. * Zeige keine Beiträge an: Beiträge von diesem Kontakt werden in keinem Kanal angezeigt. -Voreingestellte Kanäle ---- +## Voreingestellte Kanäle * Für Dich: Beiträge von Kontakten mit denen du interagierst und die mit dir interagieren. Im Detail bestehend aus: * Beiträge von Leuten, mit denen du überdurchschnittlich viel interagierst. @@ -38,8 +34,7 @@ Voreingestellte Kanäle * Audio: Beiträge mit Audio. * Videos: Beiträge mit Videos. -Vom Benutzer eingestellte Kanäle ---- +## Vom Benutzer eingestellte Kanäle In den Einstellungen, unter "Kanäle", kannst du deine eigenen Kanäle erstellen. @@ -54,8 +49,7 @@ Jeder Kanal wird durch diese Werte definiert: * Volltextsuche: Dies kann genutzt werden um Inhalte, basierend auf dem Inhalt und ein paar zusätzlichen Schlüsselwörtern, ein- oder auszuschließen. Es nutzt die "boolean mode"-Operatoren von MariaDB: https://mariadb.com/kb/en/full-text-index-overview/#in-boolean-mode * Bilder, Videos, Audio: Wenn ausgewählt, wirst du Inhalte mit dem gewählten Medientyp sehen. Diese Optionen können kombiniert werden. Wenn keines dieser Felder ausgewählt wurde, wirst du alle Inhalte, mit oder ohne angefügten Medien, sehen. -Zusätzliche Schlüsselwörter für die Volltextsuche ---- +## Zusätzliche Schlüsselwörter für die Volltextsuche Zusätzlich zu der Suche nach Inhalten, gibt es Schlüsselwörter, die in der Volltextsuche genutzt werden können. Alternativen werden durch "|" dargestellt. diff --git a/doc/de/Chats.md b/doc/de/user/chats.md similarity index 98% rename from doc/de/Chats.md rename to doc/de/user/chats.md index 83c55e991c..ce5c50cf44 100644 --- a/doc/de/Chats.md +++ b/doc/de/user/chats.md @@ -1,7 +1,4 @@ -Chats -===== - -* [Zur Startseite der Hilfe](help) +# Chats Du hast derzeit zwei Möglichkeiten, einen Chat auf Deiner Friendica-Seite zu betreiben diff --git a/doc/de/Circles-and-Privacy.md b/doc/de/user/circles-and-privacy.md similarity index 93% rename from doc/de/Circles-and-Privacy.md rename to doc/de/user/circles-and-privacy.md index dcb5f3259f..a1df277572 100644 --- a/doc/de/Circles-and-Privacy.md +++ b/doc/de/user/circles-and-privacy.md @@ -1,7 +1,4 @@ -Circles und Privatsphäre -================== - -* [Zur Startseite der Hilfe](help) +# Circles und Privatsphäre Circles sind nur eine Ansammlung von Freunden. Aber Friendica nutzt diese, um sehr mächtige Features zur Verfügung zu stellen. @@ -45,9 +42,9 @@ Standardmäßig geht Friendica davon aus, dass alle deine Beiträge privat sein Aus diesem Grund erstellt Friendica nach der Anmeldung eine Circle, in die automatisch alle deine Kontakte hinzugefügt werden. Alle deine Beiträge sind nur auf diese Circle beschränkt. -Beachte, dass diese Einstellung von deinem Seiten-Administrator überschrieben werden kann, was bedeutet, dass alle deine Beiträge standardmäßig "öffentlich" sind (bspw. für das gesamte Internet). +Beachte, dass diese Einstellung von deinem Seiten-Administrator überschrieben werden kann, was bedeutet, dass alle deine Beiträge standardmäßig "öffentlich" sind (beispielweise für das gesamte Internet). -Wenn du deine Beiträge standardmäßig "öffentlich" haben willst, dann kannst du deine Standardzugriffsrechte auf deiner Einstellungseite ändern. +Wenn du deine Beiträge standardmäßig "öffentlich" haben willst, dann kannst du deine Standardzugriffsrechte auf deiner Einstellungsseite ändern. Dort kannst du außerdem festlegen, welchen Circles standardmäßig deine Beiträge erhalten oder in welche Circle deine neuen Kontakte standardmäßig eingeordnet werden. **Fragen der Privatssphäre, die zu beachten sind** @@ -64,19 +61,18 @@ Du musst **sehr** vorsichtig sein, wenn du Mitglieder anderer Netzwerke in einer Wenn du auf die "Kontakt bearbeiten"-Seite einer Person gehst, zeigen wir dir, ob sie Mitglied eines unsicheren Netzwerks ist oder nicht. Sobald du einen Post erstellt hast, kannst du die Zugriffsrechte nicht mehr ändern. -Innerhalb von Sekunden ist dieser an viele verschiedene Personen verschickt worden - möglicherweise bereits an alle Addressierten. +Innerhalb von Sekunden ist dieser an viele verschiedene Personen verschickt worden - möglicherweise bereits an alle Adressierten. Wenn du versehentlich eine Nachricht erstellt hast und sie zurücknehmen willst, dann ist es das beste, diese zu löschen. Wir senden eine Löschmitteilung an jeden, der deine Nachricht erhalten hat - und das sollte die Nachricht genauso schnell löschen, wie sie zunächst erstellt wurde. In vielen Fällen wird sie in weniger als einer Minute aus dem Internet gelöscht. Nochmals: das gilt für Friendica-Netzwerke. Sobald eine Nachricht an ein anderes Netzwerk geschickt wurde, kann es nicht mehr so schnell gelöscht werden und in manchen Fällen auch gar nicht mehr. -Wenn du das bisher noch nicht wusstest, dann empfehlen wir dir, deine Freunde dazu zu ermutigen, auch Friendica zu nutzen, da alle diese Privatsphären-Einstellungen innerhalb eines privatsphärenbewussten Netzwerk viel besser funktionieren. +Wenn du das bisher noch nicht wusstest, dann empfehlen wir dir, deine Freunde dazu zu ermutigen, auch Friendica zu nutzen, da alle diese Privatsphären-Einstellungen innerhalb eines privatsphärenbewussten Netzwerks viel besser funktionieren. Viele andere Netzwerke, mit denen sich Friendica verbinden kann, bieten keine Kontrolle über die Privatsphäre. -Profile, Fotos und die Privatsphäre -============================= +# Profile, Fotos und die Privatsphäre Die dezentralisierte Natur von Friendica (statt eine Webseite zu haben, die alles kontrolliert, gibt es viele Webseiten, die Information austauschen) hat in der Kommunikation mit anderen Seiten einige Konsequenzen. Du solltest dir über einige Dinge bewusst sein, um am besten entscheiden zu können, wie du mit deiner Privatsphäre umgehst. @@ -90,7 +86,7 @@ Wir können die Identität von Friendica-Nutzern prüfen, da es hierfür einen M Deine Freunde anderer Netzwerke werden deine privaten Fotos nicht sehen können, da wir deren Identität nicht überprüfen können. Unsere Entwickler arbeiten an einer Lösung, um deinen Freunden den Zugriff zu ermöglichen - unabhängig, zu welchem Netzwerk sie gehören. -Wir nehmen hingegen Privatsphäre ernst und agieren nicht wie andere Netzwerke, die __nur so tun__ als ob deine Fotos privat sind, sie aber trotzdem anderen ohne Identitätsprüfung zeigen. +Wir nehmen hingegen Privatsphäre ernst und agieren nicht wie andere Netzwerke, die __nur so tun__, als ob deine Fotos privat sind, sie aber trotzdem anderen ohne Identitätsprüfung zeigen. **Profile** diff --git a/doc/de/Connectors.md b/doc/de/user/connectors.md similarity index 63% rename from doc/de/Connectors.md rename to doc/de/user/connectors.md index fe2d739fd5..8756c1cd2b 100644 --- a/doc/de/Connectors.md +++ b/doc/de/user/connectors.md @@ -1,38 +1,33 @@ -Konnektoren (Connectors) -========== +# Konnektoren (Connectors) -* [Zur Startseite der Hilfe](help) - -Konnektoren erlauben es Dir, Dich mit anderen sozialen Netzwerken zu verbinden. +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. +Für Bluesky 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. -Anleitung, um sich mit Personen in bestimmten Netzwerken zu verbinden -========================================================== +# Anleitung, um sich mit Personen in bestimmten Netzwerken zu verbinden -**Friendica** +## Friendica -Du kannst Dich verbinden, indem Du die Adresse Deiner Identität (<dein_nick>@<dein_friendica-host>) auf der "Verbinden"-Seite des Friendica-Nutzers eingibst. -Ebenso kannst Du deren Identitäts-Adresse in der "Verbinden"-Box auf Deiner ["Kontakt"-Seite](contacts) eingeben. +Du kannst Dich verbinden, indem Du die Adresse Deiner Identität (<dein_nick>@<dein_friendica-host>) auf der "Verbinden"-Seite des Friendica-Nutzers eingibst. +Ebenso kannst Du deren Identitäts-Adresse in der "Verbinden"-Box auf Deiner ["Kontakt"-Seite](contact) eingeben. +## Diaspora -**Diaspora** +Füge die Diaspora-Identitäts-Adresse (z.B. name@diasporapod.com)auf Deiner ["Kontakte"-Seite](contact) in das Feld "Neuen Kontakt hinzufügen" ein. -Füge die Diaspora-Identitäts-Adresse (z.B. name@diasporapod.com)auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein. +## Blogger, WordPress, RSS feeds, andere Webseiten -**Blogger, Wordpress, RSS feeds, andere Webseiten** - -Trage die URL auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein. +Trage die URL auf Deiner ["Kontakte"-Seite](contact) in das Feld "Neuen Kontakt hinzufügen" ein. Du hast keine Möglichkeit, diesen Kontakten zu antworten. -Das erlaubt Dir, Dich mit Millionen von Seiten im Internet zu _verbinden_. -Alles, was dafür nötig ist, ist dass die Seite einen Feed im RSS- oder Atom Syndication-Format nutzt und welches einen Autoren und ein Bild zur Seite liefert. +Das erlaubt Dir, Dich mit Millionen von Seiten im Internet zu _verbinden_. +Alles, was dafür nötig ist, ist dass die Seite einen Feed im RSS- oder Atom Syndication-Format nutzt und welches einen Autoren und ein Bild zur Seite liefert. -**Email** +## Email -Konfiguriere den Email-Konnektor auf Deiner [Einstellungsseite](settings). -Wenn Du das gemacht hast, kannst Du auf Deiner ["Kontakte"-Seite](contacts) die Email-Adresse in das Feld "Neuen Kontakt hinzufügen" eintragen. -Diese Email-Adresse muss jedoch bereits mit einer Nachricht in Deinem Email-Posteingang auf dem Server liegen. +Konfiguriere den Email-Konnektor auf Deiner [Einstellungsseite](settings). +Wenn Du das gemacht hast, kannst Du auf Deiner ["Kontakte"-Seite](contact) die Email-Adresse in das Feld "Neuen Kontakt hinzufügen" eintragen. +Diese Email-Adresse muss jedoch bereits mit einer Nachricht in Deinem Email-Posteingang auf dem Server liegen. Du hast die Möglichkeit, Email-Kontakte in Deine privaten Unterhaltungen einzubeziehen. diff --git a/doc/de/events.md b/doc/de/user/events.md similarity index 99% rename from doc/de/events.md rename to doc/de/user/events.md index b4979da1da..1b64302c33 100644 --- a/doc/de/events.md +++ b/doc/de/user/events.md @@ -1,12 +1,9 @@ # Veranstaltungen -* [Zur Startseite der Hilfe](help) - Veranstaltungen sind spezielle Postings. Die Veranstaltungen, die Du und deine Kontakte teilen, können unter [/events](/events) auf deiner Instanz aufgefunden werden. Um da hinzukommen gehe über den Tab "Veranstalltungen", abhänig von dem Theme, das du benutzt, ist der eventuell ein zusätzlicher link im Navigationsmenü der Seite vorhanden. - ## Veranstaltungsübersicht Die Übersichtsseite zeigt den Kalender des aktuellen Monats an, plus einige Tage am Beginn und am Ende. diff --git a/doc/de/Export-Import-Contacts.md b/doc/de/user/export-import-contacts.md similarity index 69% rename from doc/de/Export-Import-Contacts.md rename to doc/de/user/export-import-contacts.md index b58752c9be..a9ce5ba043 100644 --- a/doc/de/Export-Import-Contacts.md +++ b/doc/de/user/export-import-contacts.md @@ -1,13 +1,11 @@ # Export / Import von gefolgten Kontakte -* [Home](help) - -Zusätzlich zum [Umziehen des Accounts](help/Move-Account) kannst du die Liste der von dir gefolgten Kontakte exportieren und importieren. +Zusätzlich zum [Umziehen des Accounts](help/user/move-account) kannst du die Liste der von dir gefolgten Kontakte exportieren und importieren. Die exportierte Liste wird als CSV Datei in einem zu anderen Plattformen, z.B. Mastodon, Misskey oder Pleroma, kompatiblen Format gespeichert. ## Export der gefolgten Kontakte -Um die Liste der Kontakte *denen du folgst* zu exportieren, geht die [Einstellungen Persönliche Daten exportieren](settings/userexport) und klicke den [Exportiere Kontakte als CSV](settings/userexport/contact) an. +Um die Liste der Kontakte *denen du folgst* zu exportieren, geht die [Einstellungen persönliche Daten exportieren](settings/userexport) und klicke den [Exportiere Kontakte als CSV](settings/userexport/contact) an. ## Import der gefolgten Kontakte @@ -17,6 +15,6 @@ Hier kannst du die CSV Datei auswählen und hoch laden. ### Unterstütztes Datei Format Die CSV Datei *muss* mindestens eine Spalte beinhalten. -In der ersten Spalte der Tabelle sollte *sollte* entweder das Handle oder die URL des gefolgten Kontakts. +In der ersten Spalte der Tabelle *sollte* entweder das Handle oder die URL des gefolgten Kontakts. (Ein Kontakt pro Zeile.) Alle anderen Spalten der CSV Datei werden beim Importieren ignoriert. diff --git a/doc/de/FAQ.md b/doc/de/user/faq.md similarity index 74% rename from doc/de/FAQ.md rename to doc/de/user/faq.md index 57d5569c15..1081779a11 100644 --- a/doc/de/FAQ.md +++ b/doc/de/user/faq.md @@ -1,22 +1,6 @@ -Häufig gestellte Fragen - FAQ -============== +# Häufig gestellte Fragen - FAQ -* [Zur Startseite der Hilfe](help) - -* **[Wo finde ich Hilfe?](help/FAQ#help)** -* **[Warum erhalte ich Warnungen über fehlende Zertifikate?](help/FAQ#ssl)** -* **[Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen?](help/FAQ#upload)** -* **[Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben?](help/FAQ#avatars)** -* **[Wie kann ich Friendica in einer bestimmten Sprache ansehen?](help/FAQ#language)** -* **[Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten?](help/FAQ#contacts)** -* **[Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht?](help/FAQ#removed)** -* **[Kann ich einem Hashtag folgen?](help/FAQ#hashtag)** -* **[Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen?](help/FAQ#rss)** -* **[Gibt es Clients für Friendica?](help/FAQ#clients)** - - - -### Wo finde ich Hilfe? +## Wo finde ich Hilfe? Wenn Du Probleme mit Deiner Friendica-Seite hast, dann kannst Du die Community in der [Friendica-Support-Gruppe](https://forum.friendi.ca/profile/helpers) fragen. Wenn Du Deinen Account nicht nutzen kannst, kannst Du einen Account auf einer öffentlichen Seite ([Liste](https://dir.friendica.social/servers)) nutzen. @@ -35,8 +19,7 @@ Wenn du dir keinen weiteren Friendica Account einrichten willst, kannst du auch https://github.com/github/opensource.guide/pull/807 ---> - -### Warum erhalte ich Warnungen über fehlende Zertifikate? +## Warum erhalte ich Warnungen über fehlende Zertifikate? Manchmal erhältst Du eine Browser-Warnung über fehlende Zertifikate. Diese Warnungen können drei Gründe haben: @@ -49,8 +32,8 @@ Diese Warnungen können drei Gründe haben: *(SSL (Secure Socket Layer) ist eine Technologie, die Daten auf ihrem Weg zwischen zwei Computern verschlüsselt.)* -Wenn Du noch kein SSL-Zertifikat hast, dann gibt es drei Wege, eines zu erhalten: kauf Dir eines, hole Dir ein kostenloses (z.B. bei StartSSL, WoSign, hoffentlich bald auch letsencrypt) oder kreiere Dein eigenes (nicht empfohlen). -[Weitere Informationen über die Einrichtung von SSL und warum es schlecht ist, selbst-signierte Zertifikate zu nutzen, findest Du hier.](help/SSL) +Wenn Du noch kein SSL-Zertifikat hast, dann gibt es drei Wege, eines zu erhalten: kauf Dir eines, hole Dir ein kostenloses (z.B. bei StartSSL, WoSign, hoffentlich bald auch LetsEncrypt) oder kreiere Dein eigenes (nicht empfohlen). +[Weitere Informationen über die Einrichtung von SSL und warum es schlecht ist, selbst-signierte Zertifikate zu nutzen, findest Du hier.](help/admin/ssl) Sei Dir bewusst, dass Browser-Warnungen über Sicherheitslücken etwas sind, wodurch neue Nutzer schnell das Vertrauen in das gesamte Friendica-Projekt verlieren können. Aus diesem Grund wird Friendica Red nur SSL-Zertifikate eines anerkannten Anbieters (CA, certificate authority) akzeptieren und nicht zu Seiten verbinden, die kein SSL nutzen. @@ -65,10 +48,9 @@ Wenn Du zum jetzigen Zeitpunkt noch keinen Server aufgesetzt hast, ist es sinnvo Einige erlauben die Nutzung von freien Zertifikaten oder lassen Dich ihre eigenen Zertifikate mitnutzen. Andere erlauben nur kostenpflichtige Zertifikate als eigenes Angebot bzw. von anderen Anbietern. - -### Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen? +## Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen? -Bilder können direkt im [Beitragseditor](help/Text_editor) vom Computer hochgeladen werden. +Bilder können direkt im [Beitragseditor](help/text-editor) vom Computer hochgeladen werden. Eine Übersicht aller Bilder, die auf Deinem Server liegen, findest Du unter deineSeite.de/profile/profilname/photos. Dort kannst Du auch direkt Bilder hochladen und festlegen, ob Deine Kontakte eine Nachricht über das neue Bild bekommen. @@ -79,7 +61,7 @@ Deshalb eignet sich diese Methode vor allem für Office-Dateien oder gepackte Da Wer hingegen Dateien über Dropbox, über eine auf dem eigenen Server installierte Owncloud oder über einen anderen [Filehoster](http://en.wikipedia.org/wiki/Comparison_of_file_hosting_services) einfügen will, verwendet den Link-Button. Wenn Du mit dem Link-Button (Ketten-Symbol) URLs zu anderen Seiten einfügst, versucht Friendica eine kurze Zusammenfassung als Vorschau abzurufen. -Manchmal klappts das nicht ... dann verlinke den Beitrag einfach per [url=http://example.com]freigewählter Name[/url] im Editor. +Manchmal klappt das nicht ... dann verlinke den Beitrag einfach per [url=http://example.com]freigewählter Name[/url] im Editor. Video- und Audiodateien können zwar in Beiträge eingebunden werden, allerdings geht das nicht über einen direkten Upload im Editor wie bei Fotos. Du hast zwei Möglichkeiten: @@ -88,19 +70,17 @@ Du hast zwei Möglichkeiten: 2. Wenn Du Zugang zu einem eigenen Server hast, kannst Deine Multimediadatei per FTP dort hochladen und beim Video-/Audiobutton diese URL angeben. Dann wird das Video oder die Audiodatei direkt mit einem Player in Deinem Beitrag angezeigt. Friendica verwendet zur Einbettung HTML5. Das bedeutet, dass je nach Browser und Betriebssystem andere Formate unterstützt werden, darunter WebM, MP4, MP3 und Ogg. Eine Tabelle findest Du bei Wikipedia ([Video](http://en.wikipedia.org/wiki/HTML5_video), [Audio](http://en.wikipedia.org/wiki/HTML5_audio)). -Zum Konvertieren von Videos in das lizenfreie Videoformat WebM gibt es unter Windows das kostenlose Programm [Xmedia-Recode](http://www.xmedia-recode.de/). +Zum Konvertieren von Videos in das lizenzfreie Videoformat WebM gibt es unter Windows das kostenlose Programm [Xmedia-Recode](http://www.xmedia-recode.de/). - -### Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben? +## Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben? Ja. Auf Deiner ["Profile verwalten/editieren"-Seite](../profiles) wählst Du zunächst das gewünschte Profil aus. -Anschließend siehst Du eine Seite mit allen Infos zu diesem Profil. +Anschließend siehst Du eine Seite mit allen Informationen zu diesem Profil. Klicke nun oben auf den Link "Profilbild ändern" und lade im nächsten Fenster ein Bild von Deinem PC hoch. Um Deine privaten Daten zu schützen, wird in Beiträgen nur das Bild aus Deinem öffentlichen Profil angezeigt. - -### Wie kann ich Friendica in einer bestimmten Sprache ansehen? +## Wie kann ich Friendica in einer bestimmten Sprache ansehen? Die Sprache des Friendica Interfaces kann durch den `lang` Parameter un der URL beeinflusst werden. Das Argument des Parameters ist ein [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) Code. @@ -114,8 +94,7 @@ auf Deutsch: https://social.example.com/profile/example?lang=de. - -### Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten? +## Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten? Wir verhindern direkte Kommunikation mit blockierten Kontakten. Sie gehören nicht zu den Empfängern beim Versand von Beiträgen und deren Beiträge werden auch nicht importiert. @@ -134,30 +113,27 @@ Dabei werden auch Kommentare dieser Person in Beiträgen Deiner Freunde blockier Ein archivierter Kontakt bedeutet, dass Kommunikation nicht möglich ist und auch nicht versucht wird (das ist z.B. sinnvoll, wenn eine Person zu einem neuen Server gewechselt ist und das alte Profil gelöscht hat). Anders als beim Blockieren werden existierende Beiträge, die vor der Archivierung erstellt wurden, weiterhin angezeigt. -Ein versteckter Kontakt wird in keiner "Freundeliste" erscheinen (außer für dich). -Trotzdem wird ein versteckter Kontakt normal in Unterhaltungen angezeigt - was für andere Kontakte ein Hinweis sein kann, dass diese Person als versteckter Kontakt in Deiner Liste ist. +Ein versteckter Kontakt wird in keiner "Freundesliste" erscheinen (außer für dich). +Trotzdem wird ein versteckter Kontakt normal in Unterhaltungen angezeigt - was für andere Kontakte ein Hinweis sein kann, dass diese Person als versteckter Kontakt in deiner Liste ist. - -### Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht? +## Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht? Wenn Du Deinen Account löschst, wird sofort der gesamte Inhalt auf Deinem Server gelöscht und ein Löschbefehl an alle Deine Kontakte verschickt. Dadurch wirst Du ebenfalls aus dem globalen Verzeichnis gelöscht. Dieses Vorgehen setzt voraus, dass Dein Profil für 24 Stunden weiterhin "teilweise" verfügbar sein wird, um eine Verbindung zu allen Deinen Kontakten ermöglicht. Wir können also Dein Profil blockieren und es so erscheinen lassen, als wären alle Daten sofort gelöscht, allerdings warten wir 24 Stunden (bzw. bis alle Deine Kontakte informiert wurden), bevor wir die Daten auch physikalisch löschen. - -### Kann ich einem Hashtag folgen? +## Kann ich einem Hashtag folgen? Ja. Füge die Tags zu Deinen gespeicherten Suchen hinzu, sie werden automatisch auf der Netzwerk-Seite auftauchen. Bitte beachte, dass Deine Antworten auf solche Posts aus technischen Gründen nicht unter dem "Persönlich"-Reiter auf der Netzwerk-Seite und der gesamte Thread nicht per API zu sehen sind. - -### Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen? +## Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen? Wenn Du die Beiträge Deines Accounts mit RSS teilen willst, dann kannst Du einen der folgenden Links nutzen: -#### RSS-Feed Deiner Beiträge +### RSS-Feed Deiner Beiträge deineSeite.de/feed/[profilname]/posts @@ -165,7 +141,7 @@ Beispiel: Friendica Support https://forum.friendi.ca/feed/helpers/posts -#### RSS-Feed all deiner Beiträge und Antworten +### RSS-Feed all deiner Beiträge und Antworten deineSeite.de/dfrn_poll/feed/[profilname]/comments @@ -173,18 +149,17 @@ Beispiel: Friendica Support https://forum.friendi.ca/feeds/helpers/comments -#### RSS-Feed all deiner Aktivitäten +### RSS-Feed all deiner Aktivitäten deineSeite.de/feed/[profilname]/ - -### Gibt es Clients für Friendica? +## Gibt es Clients für Friendica? -Friendica unterstützt [Mastodon API](help/API-Mastodon) und [Twitter API | gnusocial](help/api). +Friendica unterstützt [Mastodon API](help/spec/api/mastodon) und [Twitter API | gnusocial](help/spec/api/index). Das bedeutet, du kannst einge der Mastodon und Twitter Clients für Friendica verwenden. Die verfügbaren Features sind Abhängig vom Client, so dass diese teils unterschiedlich sein können. -#### Android +### Android * [AndStatus](http://andstatus.org) ([F-Droid](https://f-droid.org/repository/browse/?fdid=org.andstatus.app), [Google Play](https://play.google.com/store/apps/details?id=org.andstatus.app)) * [B4X for Pleroma & Mastodon](https://github.com/AnywhereSoftware/B4X-Pleroma) @@ -202,21 +177,21 @@ Die verfügbaren Features sind Abhängig vom Client, so dass diese teils untersc * [twitlatte](https://github.com/moko256/twitlatte) * [Yuito](https://github.com/accelforce/Yuito) -#### SailfishOS +### SailfishOS * [Friendly](https://openrepos.net/content/fabrixxm/friendly#comment-form) -#### iOS +### iOS -* [B4X for Pleroma & Mastodon](https://www.b4x.com/) ([AppStore](https://apps.apple.com/app/b4x-pleroma/id1538396871), [GitHub](https://github.com/AnywhereSoftware/B4X-Pleroma)) -* [Fedi](https://fediapp.com) ([AppStore](https://apps.apple.com/de/app/fedi-for-pleroma-and-mastodon/id1478806281)) -* [Mastodon](https://joinmastodon.org/apps)([AppStore](https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974)) -* [Roma](https://www.roma.rocks/)([AppStore](https://apps.apple.com/de/app/roma-for-pleroma-and-mastodon/id1445328699)) -* [Stella*](https://www.stella-app.net/) ([AppStore](https://apps.apple.com/us/app/stella-for-mastodon-twitter/id921372048)) -* [Tooot](https://tooot.app/) ([AppStore](https://apps.apple.com/app/id1549772269), [GitHub](https://github.com/tooot-app)), Datensammlung (nicht mit Identität verknüpft) -* [Tootle](https://mastodon.cloud/@tootleapp) ([AppStore](https://apps.apple.com/de/app/tootle-for-mastodon/id1236013466)), letztes update: 2020 +* [B4X for Pleroma & Mastodon](https://www.b4x.com/) ([App Store](https://apps.apple.com/app/b4x-pleroma/id1538396871), [GitHub](https://github.com/AnywhereSoftware/B4X-Pleroma)) +* [Fedi](https://fediapp.com) ([App Store](https://apps.apple.com/de/app/fedi-for-pleroma-and-mastodon/id1478806281)) +* [Mastodon](https://joinmastodon.org/apps)([App Store](https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974)) +* [Roma](https://www.roma.rocks/)([App Store](https://apps.apple.com/de/app/roma-for-pleroma-and-mastodon/id1445328699)) +* [Stella*](https://www.stella-app.net/) ([App Store](https://apps.apple.com/us/app/stella-for-mastodon-twitter/id921372048)) +* [Tooot](https://tooot.app/) ([App Store](https://apps.apple.com/app/id1549772269), [GitHub](https://github.com/tooot-app)), Datensammlung (nicht mit Identität verknüpft) +* [Tootle](https://mastodon.cloud/@tootleapp) ([App Store](https://apps.apple.com/de/app/tootle-for-mastodon/id1236013466)), letztes update: 2020 -#### Linux +### Linux * [Choqok](https://choqok.kde.org) * [Whalebird](https://whalebird.social) @@ -224,12 +199,12 @@ Die verfügbaren Features sind Abhängig vom Client, so dass diese teils untersc * [Toot](https://toot.readthedocs.io/en/latest/) * [Tootle](https://github.com/bleakgrey/tootle) -#### macOS +### macOS -* [Mastonaut](https://mastonaut.app/) ([AppStore](https://apps.apple.com/us/app/mastonaut/id1450757574)), kostet ~8€ -* [Whalebird](https://whalebird.social/en/desktop/contents) ([AppStore](https://apps.apple.com/de/app/whalebird/id1378283354), [GitHub](https://github.com/h3poteto/whalebird-desktop)) +* [Mastonaut](https://mastonaut.app/) ([App Store](https://apps.apple.com/us/app/mastonaut/id1450757574)), kostet ~8€ +* [Whalebird](https://whalebird.social/en/desktop/contents) ([App Store](https://apps.apple.com/de/app/whalebird/id1378283354), [GitHub](https://github.com/h3poteto/whalebird-desktop)) -#### Web +### Web * [Halcyon](https://www.halcyon.social/) * [Pinafore](https://github.com/nolanlawson/pinafore) diff --git a/doc/de/Making-Friends.md b/doc/de/user/making-friends.md similarity index 88% rename from doc/de/Making-Friends.md rename to doc/de/user/making-friends.md index 041365103c..205409cf73 100644 --- a/doc/de/Making-Friends.md +++ b/doc/de/user/making-friends.md @@ -1,7 +1,4 @@ -Freunde finden -============== - -* [Zur Startseite der Hilfe](help) +# Freunde finden Freundschaft kann in Friendica viele verschiedene Bedeutungen annehmen. Aber lasst es uns einfach halten, du willst einfach mit jemandem befreundet sein. @@ -12,23 +9,23 @@ Das Verzeichnis ist in zwei Teile aufgeteilt. Wenn du auf den "Verzeichnis"-Button klickst, wirst du zunächst alle Mitglieder deines Servers sehen, die sich dazu entschlossen haben, angezeigt zu werden. Außerdem siehst du dort einen Link zum globalen Verzeichnis. Wenn du dich durch das globale Verzeichnis klickst, siehst du alle Nutzer weltweit auf allen Servern, die sich entschlossen haben, im Verzeichnis zu erscheinen. -Du wirst außerdem den Link "Show Community Groups" sehen, welcher dich zu Gruppen und Fan-Seiten führt. +Du wirst zudem den Link "Show Community Groups" sehen, welcher dich zu Gruppen und Fan-Seiten führt. Du verbindest dich mit Personen und Gruppen auf die gleiche Art, wobei Gruppen deine Anfrage automatisch annehmen, wohingegen ein Mensch dich erst manuell bestätigen muss. *Mit anderen Friendica-Nutzern verbinden* Besuche ihr Profil. Direkt unter dem Profilfoto ist das Wort "Verbinden" (bzw. "Connect" in einem englischsprachigem Profil). -Klicke drauf und du gelangst zur "Verbinden"-Seite. +Klicke darauf und du gelangst zur "Verbinden"-Seite. Dort wirst du nach deiner Identitätsadresse gefragt. Das ist nötig, damit die Seite dein Profil finden kann. *Was kommt in die Box?* Wenn deine Friendica-Seite "demo.friendica.com" heißt und dein Nutzername/Spitzname auf der Seite "bob" ist, dann wäre es "bob@demo.friendica.com". -Wie du siehst, sieht es wie eine Email-Adresse aus. +Wie du siehst, sieht es wie eine E-Mail-Adresse aus. Das ist beabsichtigt, da sich die Leute das so leichter merken können. -Du *kannst* auch die URL deiner Startseite eintragen, wie z.B. "http://demo.friendica.com/profile/bob", aber der Email-Adressen-Stil ist einfacher. +Du *kannst* auch die URL deiner Startseite eintragen, wie z.B. "http://demo.friendica.com/profile/bob", aber der E-Mail-Adressen-Stil ist einfacher. Wenn du die "Verbinden"-Seite bestätigt hast, kommst du zurück zu deiner Seite, um dort die Anfrage zu bestätigen. Wenn du das gemacht hast, können beide Seiten miteinander kommunizieren, um den Prozess abzuschließen (sobald dein neuer Freund die Anfrage bestätigt hat). @@ -45,7 +42,7 @@ Wenn du z.B. "bob" auf quitter.se (eine GNU Social-Seite) kennst, dann kannst du Tatsächlich kannst du jedem und jeder Website folgen, der/die einen Syndication-Feed (RSS/Atom etc.) zur Verfügung stellt. Wenn wir einen Informationsstrom und einen Namen dazu finden, können wir auch versuchen, uns damit zu verbinden. -Wenn du deine Email-Postfachverbindung auf deiner Einstellungsseite konfiguriert hast, dann kannst du die Email-Adresse jeder Person eintragen, die dir schon eine Nachricht an dein Postfach geschickt hat und bereits in deinem sozialen Stream erscheint. +Wenn du deine E-Mail-Postfachverbindung auf deiner Einstellungsseite konfiguriert hast, dann kannst du die E-Mail-Adresse jeder Person eintragen, die dir schon eine Nachricht an dein Postfach geschickt hat und bereits in deinem sozialen Stream erscheint. Du kannst diesen Personen außerdem von Friendica aus antworten. Leute können sich ebenfalls von anderen Netzwerken aus mit dir befreunden. diff --git a/doc/de/Move-Account.md b/doc/de/user/move-account.md similarity index 80% rename from doc/de/Move-Account.md rename to doc/de/user/move-account.md index 2573113bba..bc3c7e1523 100644 --- a/doc/de/Move-Account.md +++ b/doc/de/user/move-account.md @@ -1,8 +1,4 @@ -Accounts Umziehen -================= - -* [Zur Startseite der Hilfe](help) - +# Accounts Umziehen ! **Dies ist ein experimentelles Feature** @@ -10,8 +6,8 @@ Accounts Umziehen Unter "Einstellungen" -> "[Persönliche Daten exportieren](uexport)" aufrufen. "Account exportieren" anklicken und die Daten speichern. -Diese Datei enthält Details über dich, deine Kontakte, Gruppen und persönliche Einstellungen. -Außerdem enthält sie deinen geheimen Schlüssel mit dem du dich deinen Kontakten gegenüber ausweist. +Diese Datei enthält Details über dich, deine Kontakte, Gruppen und persönliche Einstellungen. +Außerdem enthält sie deinen geheimen Schlüssel, mit dem du dich deinen Kontakten gegenüber ausweist. **Speichere diese Datei an einem sicheren Ort**! @@ -24,11 +20,11 @@ Hier kann dies nur der Administrator selber durchführen. Lege auf dem neuen Server auf keinen Fall einen gleichnamigen Account an! user import muss anstelle des Registrierens verwendet werden. -Wähle die gesicherte Account Datei aus und klicke "Importieren". +Wähle die gesicherte Account-Datei aus und klicke "Importieren". -Friendica wird nun deinen Account auf dem neuen Server wiederherstellen, mit all deinen Friendica Kontakten und Gruppen. +Friendica wird nun deinen Account auf dem neuen Server wiederherstellen, mit all deinen Friendica Kontakten und Gruppen. An deine Friendica Kontakte wird außerdem eine Nachricht gesendet um sie über deine neue Adresse zu informieren. -Wenn deine Kontakte ihren Account auf einem aktuellen Server haben werden deine Kontaktdetails automatisch aktualisiert. +Wenn deine Kontakte ihren Account auf einem aktuellen Server haben, werden deine Kontaktdetails automatisch aktualisiert. Neuere Diaspora Server unterstützen ebenfalls eine Umzugsbenachrichtigung. diff --git a/doc/de/user/quick-start/finally.md b/doc/de/user/quick-start/finally.md new file mode 100644 index 0000000000..6863417f50 --- /dev/null +++ b/doc/de/user/quick-start/finally.md @@ -0,0 +1,14 @@ +# ... und zuletzt + +Und damit sind wir auch schon am Ende der Schnellstartanleitung. + +Hier sind noch einige weitere Dinge, die Dir den Start vereinfachen können. + +**Gruppen** + +- [Friendica Support](https://forum.friendi.ca/profile/helpers) - Probleme? Dann ist das der Platz, um zu fragen! + +**Dokumentation** + +- [Zu weiteren Netzwerken verbinden](help/user/connectors) +- [Zur Startseite der Hilfe](help) diff --git a/doc/de/Quick-Start-groupsandpages.md b/doc/de/user/quick-start/groups-and-pages.md similarity index 76% rename from doc/de/Quick-Start-groupsandpages.md rename to doc/de/user/quick-start/groups-and-pages.md index d4ea55d3d0..5f1d258518 100644 --- a/doc/de/Quick-Start-groupsandpages.md +++ b/doc/de/user/quick-start/groups-and-pages.md @@ -1,14 +1,11 @@ -Gruppen und Seiten -========== - -* [Zur Startseite der Hilfe](help) +# Gruppen und Seiten Hier siehst Du das globale Verzeichnis. Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken und wieder hierher kommen. -Auf dieser Seite findest Du eine Zusammenstellung von Gruppen. +Auf dieser Seite findest Du eine Zusammenstellung von Gruppen. Gruppen sind keine realen Personen. -Sich mit diesen zu verbinden ist, als wenn man jemanden auf Facebook "liked" ("gefällt mir") oder wenn man sich in einem Forum anmeldet. +Sich mit diesen zu verbinden ist, als wenn man jemanden auf Facebook "liked" ("gefällt mir") oder wenn man sich in einem Forum anmeldet. Du musst nicht unsicher sein, ob Du jemandem zu nahe trittst, wenn Du Dich so ohne weiteres mit einer Gruppe verbindest; es handelt sich eben nicht um reale Personen. Wenn Du Dich mit einer Gruppe verbindest, erscheinen alle Nachrichten der Gruppe in Deinem "Netzwerk"-Tab. @@ -19,8 +16,6 @@ Suche Dir einfach eine Gruppe und füge sie so hinzu, wie Du auch normale Freund Es gibt eine Menge Gruppen. Solltest Du beim Stöbern durch die vielen Gruppen nicht wieder hierher zurück finden, so nutze einfach den Link oben auf dieser Seite. -Wenn Du einige Gruppen hinzugefügt hast, gehe weiter zum nächsten Schritt. - - - +Wenn Du einige Gruppen hinzugefügt hast, gehe [weiter zum nächsten Schritt](help/user/quick-start/finally). + diff --git a/doc/de/Quick-Start-guide.md b/doc/de/user/quick-start/guide.md similarity index 70% rename from doc/de/Quick-Start-guide.md rename to doc/de/user/quick-start/guide.md index 6260bf97fc..2f4e24a731 100644 --- a/doc/de/Quick-Start-guide.md +++ b/doc/de/user/quick-start/guide.md @@ -1,36 +1,31 @@ -Erste Schritte... -========== +# Erste Schritte... -* [Zur Startseite der Hilfe](help) +Als Erstes: Gehe sicher, dass Du eingeloggt bist. +Wenn Du noch nicht eingeloggt bist, kannst Du das in dem Fenster unten machen. -Als Erstes: Gehe sicher, dass Du eingeloggt bist. -Wenn Du noch nicht eingeloggt bist, kannst Du das in dem Fenster unten machen. - -Sobald dies geschehen ist, schaust Du auf die Netzwerkseite Deines Profils. +Sobald dies geschehen ist, schaust Du auf die Netzwerkseite Deines Profils. Klicke auf den Reiter "Pinnwand". -Hier sieht es ein wenig wie auf (D)einer Facebook-Seite aus. -Du findest hier alle Deine Statusmeldungen und Nachrichten Deiner Freunde, die direkt auf Deine "Pinnwand" ("Wall") geschrieben haben. -Um Deinen Status einzutragen, klicke einfach auf die Box oben, in der "Teilen" steht. -Wenn Du das machst, vergrößert sich die Box, und Du kannst nun Deinen Text eintragen, mit Hilfe einiger Formatierungsoptionen wie fett, kursiv, unterstrichen formatieren und ebenfalls Bilder und Links hinzufügen. -Unten findest Du in diesem Feld weitere Knöpfe, mit denen Du Bilder und Dateien von Deinem Computer hochladen, Webseiten mit einem Kurztext teilen und Video- und Audiodateien aus dem Internet einfügen kannst. -Außerdem kannst Du hier eintragen, wo Du gerade bist. +Hier sieht es ein wenig wie auf (D)einer Facebook-Seite aus. +Du findest hier alle Deine Statusmeldungen und Nachrichten Deiner Freunde, die direkt auf Deine "Pinnwand" ("Wall") geschrieben haben. +Um Deinen Status einzutragen, klicke einfach auf die Box oben, in der "Teilen" steht. +Wenn Du das machst, vergrößert sich die Box, und Du kannst nun Deinen Text eintragen, mit Hilfe einiger Formatierungsoptionen wie fett, kursiv, unterstrichen formatieren und ebenfalls Bilder und Links hinzufügen. +Unten findest Du in diesem Feld weitere Knöpfe, mit denen Du Bilder und Dateien von Deinem Computer hochladen, Webseiten mit einem Kurztext teilen und Video- und Audiodateien aus dem Internet einfügen kannst. +Außerdem kannst Du hier eintragen, wo Du gerade bist. -Wenn Du Deinen Beitrag ("Post") geschrieben hast, kannst Du auf das "Schloss"-Symbol klicken und festlegen, wer Deinen Beitrag sehen kann. -Wenn Du dieses Symbol nicht anklickst, ist Dein Beitrag öffentlich, bzw. es werden deine Grundeinstellungen verwendet, wenn diese nicht öffentlich sind. +Wenn Du Deinen Beitrag ("Post") geschrieben hast, kannst Du auf das "Schloss"-Symbol klicken und festlegen, wer Deinen Beitrag sehen kann. +Wenn Du dieses Symbol nicht anklickst, ist Dein Beitrag öffentlich, bzw. es werden deine Grundeinstellungen verwendet, wenn diese nicht öffentlich sind. Ein öffentlicher Beitrag ist sichbar für -
    -
  • Besucher Deines Profils
  • -
  • Besucher Deiner "Gemeinschafts"-Seite
  • -
  • Besucher der Profile Deiner Kontakte
  • -
  • Suchmaschinen
  • -
+- Besucher Deines Profils +- Besucher Deiner "Gemeinschafts"-Seite +- Besucher der Profile Deiner Kontakte +- Suchmaschinen + Auch wenn Du Deinen Server so konfiguriert hast, dass der Zugriff von außerhalb des Friendica-Netzwerks theoretisch nicht möglich ist, so ist Dein Beitrag über die Profile Deiner Kontakte sichtbar, wenn deren Knoten solche Zugriffe zulassen. -Probiere es doch einfach mal aus. Wenn Du fertig bist, schauen wir uns den "Netzwerk"-Tab an. - - +Probiere es doch einfach mal aus. Wenn Du fertig bist, schauen wir uns den ["Netzwerk"-Tab](help/user/quick-start/network) an. + diff --git a/doc/de/Quick-Start-makingnewfriends.md b/doc/de/user/quick-start/making-new-friends.md similarity index 71% rename from doc/de/Quick-Start-makingnewfriends.md rename to doc/de/user/quick-start/making-new-friends.md index 701fba505f..d0b0d986f9 100644 --- a/doc/de/Quick-Start-makingnewfriends.md +++ b/doc/de/user/quick-start/making-new-friends.md @@ -1,10 +1,7 @@ -Neue Freunde finden -============== - -* [Zur Startseite der Hilfe](help) +# Neue Freunde finden Hier siehst Du die Kontaktvorschläge. -Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken und wieder hierher kommen. +Wenn Du Dich mal verirrt hast, kannst Du [diesen Link klicken](help/user/quick-start/making-new-friends) und wieder hierher kommen. Diese Seite funktioniert in etwa wie die Seite für Kontaktvorschläge in Facebook. Jeder auf dieser Liste hat zugestimmt, als Kontaktvorschlag zu erscheinen. @@ -21,8 +18,6 @@ Jetzt, nachdem Du jemanden hinzugefügt hast, weißt Du vielleicht nicht mehr, w Klicke einfach auf den Link oben auf dieser Seite und Du gelangst zur Seite mit den Kontaktvorschlägen zurück, um weitere Personen hinzuzufügen. Du willst nicht einfach Personen hinzufügen, die du nicht kennst? -Kein Problem - an dieser Stelle kommen wir zu den Gruppen und Seiten. - - - +Kein Problem - an dieser Stelle kommen wir zu den [Gruppen und Seiten](help/user/quick-start/groups-and-pages). + diff --git a/doc/de/Quick-Start-network.md b/doc/de/user/quick-start/network.md similarity index 54% rename from doc/de/Quick-Start-network.md rename to doc/de/user/quick-start/network.md index 0c6f828355..affa2c3d30 100644 --- a/doc/de/Quick-Start-network.md +++ b/doc/de/user/quick-start/network.md @@ -1,20 +1,15 @@ -Deine "Netzwerk"-Seite -============== +# Deine "Netzwerk"-Seite -* [Zur Startseite der Hilfe](help) +Dies ist Dein "Netzwerk"-Tab. +Wenn Du Dich mal verirrt hast, kannst Du [diesen Link klicken](help/user/quick-start/network), um wieder hierher zu kommen. -Dies ist Dein "Netzwerk"-Tab. -Wenn Du Dich mal verirrt hast, kannst Du diesen Link klicken, um wieder hierher zu kommen. - -Diese Seite ist ein wenig wie die News-Seite in Facebook oder der Stream in Diaspora. -Hier findest Du alle Beiträge Deiner Kontakte, Gruppen und Feeds, die Du eingetragen hast. -Wenn Du neu bist, siehst Du hier noch nichts, falls Du an Deinem Status im letzten Schritt noch nichts geändert haben solltest. -Wenn Du bereits ein paar Freunde gefunden hast, so findest Du hier ihre Beiträge. +Diese Seite ist ein wenig wie die News-Seite in Facebook oder der Stream in Diaspora. +Hier findest Du alle Beiträge Deiner Kontakte, Gruppen und Feeds, die Du eingetragen hast. +Wenn Du neu bist, siehst Du hier noch nichts, falls Du an Deinem Status im letzten Schritt noch nichts geändert haben solltest. +Wenn Du bereits ein paar Freunde gefunden hast, so findest Du hier ihre Beiträge. Du kannst ihre Beiträge von hier aus kommentieren, mitteilen, dass Du den Beitrag magst oder ablehnst (Daumen hoch, Daumen runter) oder die Profile durch einen Klick auf deren Namen besuchen und dort auf deren "Pinnwand" ("Wall") Nachrichten schreiben. -Nun wollen wir diese Seite mit Inhalt füllen. -Der erste Schritt ist es, Leute zu Deinem Account hinzuzufügen. - - - +Nun wollen wir diese Seite mit Inhalt füllen. +Der erste Schritt ist es, [Leute zu Deinem Account hinzuzufügen](help/user/quick-start/making-new-friends). + diff --git a/doc/de/Remove-Account.md b/doc/de/user/remove-account.md similarity index 76% rename from doc/de/Remove-Account.md rename to doc/de/user/remove-account.md index 5cba208fea..5b2dbcf5e2 100644 --- a/doc/de/Remove-Account.md +++ b/doc/de/user/remove-account.md @@ -1,23 +1,20 @@ -Accounts löschen -============== - -* [Zur Startseite der Hilfe](help) +# Accounts löschen Wir freuen uns nicht, wenn Leute Friendica verlassen, aber wenn du deinen Account löschen willst, dann besuche die folgende URL [Lösche mich (http://NamederSeite/settings/removeme)](../settings/removeme) -in deinem Webbrowser. Du musst dabei eingeloggt sein. +in deinem Webbrowser. Du musst dabei eingeloggt sein. -Du wirst nach deinem Passwort gefragt, um die Anfrage zu bestätigen. +Du wirst nach deinem Passwort gefragt, um die Anfrage zu bestätigen. Wenn dieses mit deinem gespeichertem Passwort übereinstimmt, dann wird dein Account als "gelöscht" markiert. Dies passiert sofort und kann nicht rückgängig gemacht werden. -Die meisten Deiner Inhalte und Benutzerdaten werden kurzfristig danach durch Hintergrundprozesse gelöscht. +Die meisten deiner Inhalte und Benutzerdaten werden kurzfristig danach durch Hintergrundprozesse gelöscht. Parallel dazu senden wir eine Mitteilung an die Server deiner Kontakte, damit sie deine dort vorliegenden Daten ebenfalls löschen. Wir haben keinen Einfluss darauf, wie sorgfältig und ob überhaupt diese Systeme der Löschaufforderung nachgehen. -Aus technischen Gründen benötigen wir für die Übetragung dieser Mitteilung ein paar Benutzerdaten. +Aus technischen Gründen benötigen wir für die Übertragung dieser Mitteilung ein paar Benutzerdaten. Diese Daten werden dann nach einer Frist von etwa sieben Tagen ebenfalls gelöscht. Wir speichern deinen Benutzernamen dauerhaft, damit sich niemand einen Account unter deinem Spitznamen anlegen kann. diff --git a/doc/de/Tags-and-Mentions.md b/doc/de/user/tags-and-mentions.md similarity index 97% rename from doc/de/Tags-and-Mentions.md rename to doc/de/user/tags-and-mentions.md index 8ab5bb581d..adb5f96a08 100644 --- a/doc/de/Tags-and-Mentions.md +++ b/doc/de/user/tags-and-mentions.md @@ -1,7 +1,4 @@ -Tags und Erwähnungen -================= - -* [Zur Startseite der Hilfe](help) +# Tags und Erwähnungen Wie viele andere soziale Netzwerke benutzt auch Friendica eine spezielle Schreibweise in seinen Nachrichten, um Tags oder kontextbezogene Links zu anderen Beiträgen hervorzuheben. diff --git a/doc/de/Text_comment.md b/doc/de/user/text-comment.md similarity index 83% rename from doc/de/Text_comment.md rename to doc/de/user/text-comment.md index c9203dfd4c..8cc1716bb5 100644 --- a/doc/de/Text_comment.md +++ b/doc/de/user/text-comment.md @@ -1,11 +1,8 @@ -Beiträge kommentieren, einordnen und löschen -========================================================== +# Beiträge kommentieren, einordnen und löschen -* [Zur Startseite der Hilfe](help) - -Hier findest du eine Übersicht über die verschiedenen Möglichkeiten, bestehende Beiträge einzuordnen und zu kommentieren. +Hier findest du eine Übersicht über die verschiedenen Möglichkeiten, bestehende Beiträge einzuordnen und zu kommentieren. -Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. +Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht oder in anderer Form vorfinden. @@ -13,37 +10,37 @@ Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht ode Die einzelnen Symbole -post_thumbs_up.png Mit diesem Symbol kannst du zeigen, dass dir ein Beitrag gefällt. +post_thumbs_up.png Mit diesem Symbol kannst du zeigen, dass dir ein Beitrag gefällt. Falls du diese Eingabe zurücknehmen willst, klicke einfach ein zweites Mal auf das Symbol.

-post_thumbs_down.png Mit diesem Symbol kannst du zeigen, dass dir ein Beitrag nicht gefällt. +post_thumbs_down.png Mit diesem Symbol kannst du zeigen, dass dir ein Beitrag nicht gefällt. Falls du diese Eingabe zurücknehmen willst, klicke einfach ein zweites Mal auf das Symbol.

-post_share.png Mit diesem Symbol kannst du einen Beitrag weiter verteilen. -Einfach anklicken und sofort erscheint der Beitrag in deinem Beitragseditor. +post_share.png Mit diesem Symbol kannst du einen Beitrag weiter verteilen. +Einfach anklicken und sofort erscheint der Beitrag in deinem Beitragseditor. Am Ende des eingefügten Beitrags erscheint ein Link zum Originalbeitrag.

-post_mark.png Mit diesem Symbol kannst du einen Beitrag für dich markieren. -Markierte Beiträge erscheinen in deiner Netzwerk-Seite unter "Markierte". +post_mark.png Mit diesem Symbol kannst du einen Beitrag für dich markieren. +Markierte Beiträge erscheinen in deiner Netzwerk-Seite unter "Markierte". Wenn du die Markierung entfernen willst, klicke einfach ein zweites Mal auf das Symbol.

-post_tag.png Mit diesem Symbol kannst du einen tag zum Beitrag hinzufügen und diesen so einem bestimmten Schlagwort zuzuordnen. -Anschließend kannst du auf diesen tag klicken und alle Beiträge mit diesem tag ansehen. +post_tag.png Mit diesem Symbol kannst du einen tag zum Beitrag hinzufügen und diesen so einem bestimmten Schlagwort zuzuordnen. +Anschließend kannst du auf diesen tag klicken und alle Beiträge mit diesem tag ansehen. ACHTUNG: tags können nicht mehr entfernt werden.

-post_categorize.png Mit diesem Symbol ist es möglich, die Beiträge in bestimmte Gruppen einzuordnen. -Dies dient dazu, gewählte Beiträge nach eigenen Vorstellungen zu sortieren und wieder zu finden. +post_categorize.png Mit diesem Symbol ist es möglich, die Beiträge in bestimmte Gruppen einzuordnen. +Dies dient dazu, gewählte Beiträge nach eigenen Vorstellungen zu sortieren und wieder zu finden. Wähle eine vorhandene Gruppe oder gib einen neuen Namen ein. Die erstellten Gruppen findest du unter "Gespeicherte Ordner" in der Netzwerk-Ansicht.

post_delete.png Mit diesem Symbol löschst du deinen eigenen Beitrag bzw. entfernst einen Beitrag einer anderen Person aus deinem Stream.

-post_choose.png Mit diesem Symbol kannst du mehrere Beiträge auswählen und gesammelt löschen. +post_choose.png Mit diesem Symbol kannst du mehrere Beiträge auswählen und gesammelt löschen. Hierfür gehst du nach dem Markieren aller gewünschten Beiträge auf "Lösche die markierten Beiträge" am Ende der Seite mit allen Beiträgen.

diff --git a/doc/de/user/text-editor.md b/doc/de/user/text-editor.md new file mode 100644 index 0000000000..a67fc4597b --- /dev/null +++ b/doc/de/user/text-editor.md @@ -0,0 +1,48 @@ +# Beiträge erstellen + +Hier findest du eine Übersicht über die verschiedenen Möglichkeiten, deinen Beitrag zu bearbeiten. + +Achtung: für dieses Beispiel wurde das Thema "Diabook" genutzt. +Wenn du ein anderes Design benutzt, wirst du manche dieser Symbole gar nicht oder in anderer Form vorfinden. + + +editor + +Die einzelnen Symbole + +editor Wenn du auf dieses Symbol klickst, dann kannst du ein Bild von deinem Computer hinzufügen. +Wenn du eine Internetadresse (URL) eingeben willst, dann kannst du das "Baum"-Symbol im oberen Teil des Editors nutzen. +Wenn du ein Bild ausgewählt hast, dann erscheint eine Miniaturdarstellung des Bildes im Editor.* +

+ +paper_clip Wenn du dieses Symbol anklickst, dann kannst du weitere Dateien von deinem Computer einfügen. Eine Vorschau des Dateiinhalts erfolgt nicht.* +

+ +chain Wenn du die Kette anklickst, dann kannst du eine Internetadresse (URL) einfügen. +Im Editor erscheint automatisch eine kurze Information zum eingefügten Link.* +

+ +video Mit dieser Funktion kannst du die Internetadresse (URL) einer Videodatei einfügen. +Das Video erscheint dann mit einem Player in deinem Beitrag. +Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser verschiedene Videoformate unterstützt (z.B. WebM oder MP4). +Außerdem kannst du hier die URLs von Videos auf Youtube, Vimeo und manchen anderen Videohostern eingeben. +Die Videos werden dann mit Vorschaubild angezeigt, nach einem Klick öffnet sich ein eingebetteter Player.* +

+ +mic Mit dieser Funktion kannst du die Internetadresse (URL) einer Sound-Datei einfügen. +Da Friendica zur Einbindung [HTML5](http://en.wikipedia.org/wiki/HTML5_video) verwendet, werden je nach Browser und Betriebssystem MP3, Ogg oder AAC unterstützt. +Außerdem kannst du hier auch URLs von manchen Audiohostern wie Soundcloud eingeben, um eine dort gespeicherte Audiodatei mit Player in deinem Beitrag anzuzeigen.* +

+ +globe Wenn du dieses Symbol wählst, dann kannst du deinen Standort festlegen. +Hier reicht schon eine Angabe wie "Berlin" oder "10775". +Dieser Eintrag führt anschließend zu einer Suchanfrage bei Google Maps. +

+ +* wie du Dateien hochladen kannst, erfährst du [hier](help/faq#upload) + +**Im Folgenden findest du Symbole weiterer Themen** + +Frio frio.png + +Vier vier.png diff --git a/doc/Config.md b/doc/en/admin/config.md similarity index 98% rename from doc/Config.md rename to doc/en/admin/config.md index afd4e65277..4d8945678b 100644 --- a/doc/Config.md +++ b/doc/en/admin/config.md @@ -1,7 +1,4 @@ -Config values that can only be set in config/local.config.php -========================================================== - -* [Home](help) +# Config values that can only be set in config/local.config.php Friendica's configuration is done in two places: in PHP array configuration files and in the `config` database table. Database config values overwrite the same file config values. diff --git a/doc/FAQ-admin.md b/doc/en/admin/faq.md similarity index 56% rename from doc/FAQ-admin.md rename to doc/en/admin/faq.md index 993a6c89ef..fc403be9a3 100644 --- a/doc/FAQ-admin.md +++ b/doc/en/admin/faq.md @@ -1,22 +1,10 @@ -Frequently Asked Questions (Admin) - FAQ -============== +# Frequently asked questions (Admin) - FAQ -* [Home](help) - -* **[Can I configure multiple domains with the same code instance?](help/FAQ-admin#multiple)** -* **[Where can I find the source code of friendica, addons and themes?](help/FAQ-admin#sources)** -* **[I've changed the my email address now the admin panel is gone?](help/FAQ-admin#adminaccount1)** -* **[Can there be more then just one admin for a node?](help/FAQ-admin#adminaccount2)** -* **[The Database structure seems not to be updated. What can I do?](help/FAQ-admin#dbupdate)** - - - -### Can I configure multiple domains with the same code instance? +## Can I configure multiple domains with the same code instance? No, this function is no longer supported as of Friendica 3.3 onwards. - -### Where can I find the source code of friendica, addons and themes? +## Where can I find the source code of friendica, addons and themes? You can find the main repository [here](https://github.com/friendica/friendica). There you will always find the current stable version of friendica. @@ -25,13 +13,11 @@ Addons are listed at [this page](https://github.com/friendica/friendica-addons). If you are searching for new themes, you can find them at [github.com/bkil/friendica-themes](https://github.com/bkil/friendica-themes) - -### I've changed my email address now the admin panel is gone? +## I've changed my email address now the admin panel is gone? Have a look into your config/local.config.php and fix your email address there. - -### Can there be more then one admin for a node? +## Can there be more then one admin for a node? Yes. You just have to list more then one email address in the @@ -42,14 +28,14 @@ The listed emails need to be separated by a comma like this: 'admin_email' => 'mail1@example.com,mail2@example.com', ``` - -### The Database structure seems not to be updated. What can I do? +## The Database structure seems not to be updated. What can I do? Please have a look at the Admin panel under [DB updates](/admin/dbsync/) and follow the link to *check database structure*. This will start a background process to check if the structure is up to the current definition. You can manually execute the structure update from the CLI in the base directory of your Friendica installation by running the following command: - - bin/console dbstructure update +```sh +bin/console dbstructure update +``` if there occur any errors, please contact the [Friendica Support group](https://forum.friendi.ca/profile/helpers) or discuss in the [Friendica Admins group](https://forum.friendi.ca/profile/admins). diff --git a/doc/Improve-Performance.md b/doc/en/admin/improve-performance.md similarity index 77% rename from doc/Improve-Performance.md rename to doc/en/admin/improve-performance.md index 9134cb6c74..2dbfc1f0ac 100644 --- a/doc/Improve-Performance.md +++ b/doc/en/admin/improve-performance.md @@ -1,25 +1,20 @@ -How to improve the performance of a Friendica site -============== - -* [Home](help) +# How to improve the performance of a Friendica server Feel free to ask in the [Friendica support group](https://forum.friendi.ca/profile/helpers) if you need some clarification about the following instructions or if you need help in any other way. -System configuration --------- +## System configuration -Please go to /admin/site/ on your system and change the following values: +Please go to `/admin/site/` on your system and change the following values: Set "JPEG image quality" to 50. -This value reduces the data that is send from the server to the client. 50 is a value that doesn't influences image quality too much. +This value reduces the data that is sent from the server to the client. 50 is a value that doesn't influence image quality too much. Enable "Use MySQL full text engine" When using MyISAM (default) or InnoDB on MariaDB 10 this speeds up search. -Addons --------- +## Addons Active the following addons: @@ -43,8 +38,7 @@ They show your performance problems. Others: Everything else :) Total: The sum of all above values -Apache Webserver --------- +## Apache Webserver The following Apache modules are recommended: @@ -53,20 +47,20 @@ The following Apache modules are recommended: This module tells the client to cache the content of static files so that they aren't fetched with every request. Enable the module "mod_expires" by typing in "a2enmod expires" as root. Please add the following lines to your site configuration in the "directory" context. - - ExpiresActive on ExpiresDefault "access plus 1 week" +``` +ExpiresActive on ExpiresDefault "access plus 1 week" +``` Also see the Apache [2.2](http://httpd.apache.org/docs/2.2/mod/mod_expires.html) / [2.4](https://httpd.apache.org/docs/2.4/mod/mod_expires.html) documentation. ### Compress content This module compresses the traffic between the web server and the client. -Enable the module "mod_deflate" by typing in "a2enmod deflate" as root. +Enable the module `mod_deflate` by typing in `a2enmod deflate` as root. -Also see the Apache [2.2](http://httpd.apache.org/docs/2.2/mod/mod_deflate.html) / [2.4](https://httpd.apache.org/docs/2.4/mod/mod_deflate.html) documentation. +Also see the Apache [2.2](https://httpd.apache.org/docs/2.2/mod/mod_deflate.html) / [2.4](https://httpd.apache.org/docs/2.4/mod/mod_deflate.html) documentation. -PHP --------- +## PHP ### FCGI diff --git a/doc/en/admin/install-ejabberd.md b/doc/en/admin/install-ejabberd.md new file mode 100644 index 0000000000..dfb151d3d3 --- /dev/null +++ b/doc/en/admin/install-ejabberd.md @@ -0,0 +1,47 @@ +# Install an ejabberd with synchronized credentials + +[Ejabberd](https://www.ejabberd.im/) is a chat server that uses XMPP as messaging protocol that you can use with a large amount of clients. +In conjunction with the "xmpp" addon it can be used for a web based chat solution for your users. + +## Installation + +- Change its owner to whichever user is running the server, ie. ejabberd +```sh +chown ejabberd:ejabberd /path/to/friendica/bin/auth_ejabberd.php +``` + +- Change the access mode, so it is readable only to the user ejabberd and has exec +```sh +chmod 700 /path/to/friendica/bin/auth_ejabberd.php +``` + +- Edit your ejabberd.cfg file, comment out your auth_method and add: +``` +{auth_method, external}. +{extauth_program, "/path/to/friendica/bin/auth_ejabberd.php"}. +``` + +- Disable the module "mod_register" and disable the registration: +``` +{access, register, [{deny, all}]}. +``` + +- Enable BOSH: + - Enable the module "mod_http_bind" + - Edit this line: +``` +{5280, ejabberd_http, [captcha, http_poll, http_bind]} +``` + + - In your apache configuration for your site add this line: +``` +ProxyPass /http-bind http://127.0.0.1:5280/http-bind retry=0 +``` + +- Restart your ejabberd service, you should be able to log in with your friendica credentials + +## Other hints + +- if a user has a space or a @ in the nickname, the user has to replace these characters: + - " " (space) is replaced with "%20" + - "@" is replaced with "(a)" diff --git a/doc/Install.md b/doc/en/admin/install.md similarity index 82% rename from doc/Install.md rename to doc/en/admin/install.md index 3c162d519b..f1981a0ffb 100644 --- a/doc/Install.md +++ b/doc/en/admin/install.md @@ -1,7 +1,7 @@ -# Friendica Installation +# Friendica installation -We've tried very hard to ensure that Friendica will run on commodity hosting platforms - such as those used to host Wordpress blogs and Drupal websites. +We've tried very hard to ensure that Friendica will run on commodity hosting platforms - such as those used to host WordPress blogs and Drupal websites. We offer a manual and an automatic installation. But be aware that Friendica is more than a simple web application. @@ -12,10 +12,10 @@ This kind of functionality requires a bit more of the host system than the typic Not every PHP/MySQL hosting provider will be able to support Friendica. Many will. -But **please** review the [requirements](#Requirements) and confirm these with your hosting provider prior to installation. +But **please** review the requirements below and confirm these with your hosting provider prior to installation. ## Support -If you encounter installation issues, please let us know via the [helper](http://forum.friendi.ca/profile/helpers) or the [developer](https://forum.friendi.ca/profile/developers) group or [file an issue](https://github.com/friendica/friendica/issues). +If you encounter installation issues, please let us know via the [helper](https://forum.friendi.ca/profile/helpers) or the [developer](https://forum.friendi.ca/profile/developers) group or [file an issue](https://github.com/friendica/friendica/issues). Please be as clear as you can about your operating environment and provide as much detail as possible about any error messages you may see, so that we can prevent it from happening in the future. Due to the large variety of operating systems and PHP platforms in existence we may have only limited ability to debug your PHP installation or acquire any missing modules - but we will do our best to solve any general code issues. @@ -27,7 +27,7 @@ Due to the large variety of operating systems and PHP platforms in existence we ### Requirements -* Apache with mod_rewrite enabled and "[AllowOverride All](https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride)" so you can use a local `.htaccess` file +* Apache with `mod_rewrite` enabled and "[AllowOverride All](https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride)" so you can use a local `.htaccess` file * PHP 7.4+ * PHP *command line* access with register_argc_argv set to true in the php.ini file * Curl, GD, GMP, PDO, mbstring, MySQLi, xml, zip, IntlChar, IDN and OpenSSL extensions @@ -74,33 +74,40 @@ Clone the [friendica/friendica GitHub repository](https://github.com/friendica/f This makes the software much easier to update. The Linux commands to clone the repository into a directory "mywebsite" would be - - git clone https://github.com/friendica/friendica.git -b stable mywebsite +```sh +git clone https://github.com/friendica/friendica.git -b stable mywebsite +``` Get the addons by going into your website folder. - - cd mywebsite +```sh +cd mywebsite +``` Clone the addon repository (separately): - - git clone https://github.com/friendica/friendica-addons.git -b stable addon +```sh +git clone https://github.com/friendica/friendica-addons.git -b stable addon +``` Install the dependencies: - - bin/composer.phar run install:prod +```sh +bin/composer.phar run install:prod +``` Make sure the folder *view/smarty3* exists and is writable by the webserver user, in this case *www-data* - - mkdir -p view/smarty3 - chown www-data:www-data view/smarty3 - chmod 775 view/smarty3 +```sh +mkdir -p view/smarty3 +chown www-data:www-data view/smarty3 +chmod 775 view/smarty3 +``` If you want to use the development version of Friendica you can switch to the develop branch in the repository by running - git checkout develop - bin/composer.phar run install:prod - cd addon - git checkout develop +```sh +git checkout develop +bin/composer.phar run install:prod +cd addon +git checkout develop +``` **Be aware that the develop branch is unstable and may break your Friendica node at any time.** You should have a recent backup before updating. @@ -111,19 +118,23 @@ If you encounter a bug, please let us know. Create an empty database and note the access details (hostname, username, password, database name). Generate a strong password, then enter mysql with: - mysql +```sh +mysql +``` Then use the following script using the password you just generated: - CREATE DATABASE friendicadb; - CREATE USER 'friendica'@'localhost' IDENTIFIED BY '<>'; - GRANT ALL ON friendicadb.* TO 'friendica'@'localhost'; - FLUSH PRIVILEGES; - EXIT; +```sql +CREATE DATABASE friendicadb; +CREATE USER 'friendica'@'localhost' IDENTIFIED BY '<>'; +GRANT ALL ON friendicadb.* TO 'friendica'@'localhost'; +FLUSH PRIVILEGES; +EXIT; +``` Friendica needs the permission to create and delete fields and tables in its own database. -Please check the [troubleshooting](#Troubleshooting) section if running on MySQL 5.7.17 or newer. +Please check the Troubleshooting section below if running on MySQL 5.7.17 or newer. ### Option A: Run the installer @@ -144,42 +155,45 @@ Registration errors should all be recoverable automatically. If you get any *critical* failure at this point, it generally indicates the database was not installed correctly. You might wish to move/rename `config/local.config.php` to another name and empty (called 'dropping') the database tables, so that you can start fresh. -### Option B: Run the automatic install script +### Option B: Run the automatic installation script You have the following options to automatically install Friendica: -- creating a prepared config file (f.e. `prepared.config.php`) -- using environment variables (f.e. `MYSQL_HOST`) -- using options (f.e. `--dbhost `) +- creating a prepared config file (f.e. `prepared.config.php`) +- using environment variables (f.e. `MYSQL_HOST`) +- using options (f.e. `--dbhost `) You can combine environment variables and options, but be aware that options are prioritized over environment variables. For more information during the installation, you can use this command line option - - bin/console autoinstall -v +```sh +bin/console autoinstall -v +``` If you wish to include all optional checks, use `-a` like this statement: - - bin/console autoinstall -a +```sh +bin/console autoinstall -a +``` *If* the automatic installation fails for any reason, check the following: -* Does `config/local.config.php` already exist? If yes, the automatic installation won't start -* Are the options in the `config/local.config.php` correct? If not, edit them directly. -* Is the empty MySQL-database created? If not, create it. +* Does `config/local.config.php` already exist? If yes, the automatic installation won't start +* Are the options in the `config/local.config.php` correct? If not, edit them directly. +* Is the empty MySQL-database created? If not, create it. #### B.1: Config file You can use a prepared config file like [local-sample.config.php](/config/local-sample.config.php). Navigate to the main Friendica directory and execute the following command: - - bin/console autoinstall -f +```sh +bin/console autoinstall -f +``` #### B.2: Environment variables There are two types of environment variables. -- those you can use in normal mode too (Currently just **database credentials**) -- those you can only use during installation (because Friendica will normally ignore it) +- those you can use in normal mode too (Currently just **database credentials**) +- those you can only use during installation (because Friendica will normally ignore it) You can use the options during installation too and skip some of the environment variables. @@ -187,53 +201,56 @@ You can use the options during installation too and skip some of the environment if you don't use the option `--savedb` during installation, the DB credentials will **not** be saved in the `config/local.config.php`. -- `MYSQL_HOST` The host of the mysql/mariadb database -- `MYSQL_PORT` The port of the mysql/mariadb database -- `MYSQL_USERNAME` The username of the mysql database login (used for mysql) -- `MYSQL_USER` The username of the mysql database login (used for mariadb) -- `MYSQL_PASSWORD` The password of the mysql/mariadb database login -- `MYSQL_DATABASE` The name of the mysql/mariadb database +- `MYSQL_HOST` The host of the mysql/mariadb database +- `MYSQL_PORT` The port of the mysql/mariadb database +- `MYSQL_USERNAME` The username of the mysql database login (used for mysql) +- `MYSQL_USER` The username of the mysql database login (used for mariadb) +- `MYSQL_PASSWORD` The password of the mysql/mariadb database login +- `MYSQL_DATABASE` The name of the mysql/mariadb database **Friendica settings** -This variables wont be used at normal Friendica runtime. +These variables won't be used at normal Friendica runtime. Instead, they get saved into `config/local.config.php`. -- `FRIENDICA_URL_PATH` The URL path of Friendica (f.e. '/friendica') -- `FRIENDICA_PHP_PATH` The path of the PHP binary -- `FRIENDICA_ADMIN_MAIL` The admin email address of Friendica (this email will be used for admin access) -- `FRIENDICA_TZ` The timezone of Friendica -- `FRIENDICA_LANG` The language of Friendica +- `FRIENDICA_URL_PATH` The URL path of Friendica (f.e. '/friendica') +- `FRIENDICA_PHP_PATH` The path of the PHP binary +- `FRIENDICA_ADMIN_MAIL` The admin email address of Friendica (this email will be used for admin access) +- `FRIENDICA_TZ` The timezone of Friendica +- `FRIENDICA_LANG` The language of Friendica Navigate to the main Friendica directory and execute the following command: - - bin/console autoinstall [--savedb] +```sh +bin/console autoinstall [--savedb] +``` #### B.3: Execution options All options will be saved in the `config/local.config.php` and are overruling the associated environment variables. -- `-H|--dbhost ` The host of the mysql/mariadb database (env `MYSQL_HOST`) -- `-p|--dbport ` The port of the mysql/mariadb database (env `MYSQL_PORT`) -- `-U|--dbuser ` The username of the mysql/mariadb database login (env `MYSQL_USER` or `MYSQL_USERNAME`) -- `-P|--dbpass ` The password of the mysql/mariadb database login (env `MYSQL_PASSWORD`) -- `-d|--dbdata ` The name of the mysql/mariadb database (env `MYSQL_DATABASE`) -- `-b|--phppath ` The path of the PHP binary (env `FRIENDICA_PHP_PATH`) -- `-A|--admin ` The admin email address of Friendica (env `FRIENDICA_ADMIN_MAIL`) -- `-T|--tz ` The timezone of Friendica (env `FRIENDICA_TZ`) -- `-L|--lang ` The language of Friendica (env `FRIENDICA_LANG`) +- `-H|--dbhost ` The host of the mysql/mariadb database (env `MYSQL_HOST`) +- `-p|--dbport ` The port of the mysql/mariadb database (env `MYSQL_PORT`) +- `-U|--dbuser ` The username of the mysql/mariadb database login (env `MYSQL_USER` or `MYSQL_USERNAME`) +- `-P|--dbpass ` The password of the mysql/mariadb database login (env `MYSQL_PASSWORD`) +- `-d|--dbdata ` The name of the mysql/mariadb database (env `MYSQL_DATABASE`) +- `-b|--phppath ` The path of the PHP binary (env `FRIENDICA_PHP_PATH`) +- `-A|--admin ` The admin email address of Friendica (env `FRIENDICA_ADMIN_MAIL`) +- `-T|--tz ` The timezone of Friendica (env `FRIENDICA_TZ`) +- `-L|--lang ` The language of Friendica (env `FRIENDICA_LANG`) Navigate to the main Friendica directory and execute the following command: - - bin/console autoinstall [options] +```sh +bin/console autoinstall [options] +``` ### Prepare .htaccess file Copy `.htaccess-dist` to `.htaccess` (be careful under Windows) to have working mod-rewrite again. If you have installed Friendica into a sub directory, like */friendica/* set this path in `RewriteBase` accordingly. Example: - - cp .htaccess-dist .htaccess +```sh +cp .htaccess-dist .htaccess +``` *Note*: Do **not** rename the `.htaccess-dist` file as it is tracked by GIT and renaming will cause a dirty working directory. @@ -250,9 +267,9 @@ Another common error related to host-meta is the "Invalid profile URL." Check for a `.well-known` directory that did not come with Friendica. The preferred configuration is to remove the directory, however this is not always possible. -If there is any /.well-known/.htaccess file, it could interfere with this Friendica core requirement. -You should remove any RewriteRules from that file, or remove that whole file if appropriate. -It may be necessary to chmod the /.well-known/.htaccess file if you were not given write permissions by default. +If there is any `/.well-known/.htaccess` file, it could interfere with this Friendica core requirement. +You should remove any `RewriteRules` from that file, or remove that whole file if appropriate. +It may be necessary to `chmod` the `/.well-known/.htaccess` file if you were not given write permissions by default. ## Register the admin account @@ -268,8 +285,9 @@ You might wish to delete/rename `config/local.config.php` to another name and dr Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing. Example: - - cd /base/directory; /path/to/php bin/console.php worker +```sh +cd /base/directory; /path/to/php bin/console.php worker +``` Change "/base/directory", and "/path/to/php" as appropriate for your situation. @@ -277,8 +295,9 @@ Change "/base/directory", and "/path/to/php" as appropriate for your situation. If you are using a Linux server, run "crontab -e" and add a line like the one shown, substituting for your unique paths and settings: - - */10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker +```crontab +*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker +``` You can generally find the location of PHP by executing "which php". If you run into trouble with this section please contact your hosting provider for assistance. @@ -290,12 +309,15 @@ Once you have installed Friendica and created an admin account as part of the pr #### worker alternative: daemon Otherwise, you’ll need to use the command line on your remote server and start the Friendica daemon (background task) using the following command: - - cd /path/to/friendica; php bin/console.php daemon start +```sh +cd /path/to/friendica; php bin/console.php daemon start +``` Once started, you can check the daemon status using the following command: - cd /path/to/friendica; php bin/console.php daemon status +```sh +cd /path/to/friendica; php bin/console.php daemon status +``` After a server restart or any other failure, the daemon needs to be restarted. This could be achieved by a cronjob. @@ -303,7 +325,7 @@ This could be achieved by a cronjob. ### (RECOMMENDED) Logging & Log Rotation At this point it is recommended that you set up logging and logrotation. -To do so please visit [Settings](help/Settings) and search the 'Logs' section for more information. +To do so please visit [Settings](help/admin/settings) and search the 'Logs' section for more information. ### (RECOMMENDED) Set up a backup plan @@ -319,16 +341,23 @@ As it stores all your data, you should also have a recent dump of your Friendica Friendica looks for some well-known HTTP headers indicating a reverse-proxy terminating an HTTPS connection. While the standard from RFC 7239 specifies the use of the `Forwarded` header. - - Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2 +``` +Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2 +``` Friendica also supports a number on non-standard headers in common use. - X-Forwarded-Proto: https +``` +X-Forwarded-Proto: https +``` - Front-End-Https: on +``` +Front-End-Https: on +``` - X-Forwarded-Ssl: on +``` +X-Forwarded-Ssl: on +``` It is however preferable to use the standard approach if configuring a new server. @@ -355,12 +384,12 @@ Often this will need to be resolved with your hosting provider or (if self-hoste First check your file permissions. Your website and all contents must generally be world-readable. -Ensure that mod-rewrite is installed and working, and that your `.htaccess` file +Ensure that `mod-rewrite` is installed and working, and that your `.htaccess` file is being used. To verify the latter, create a file `test.out` containing the word "test" in the top directory of Friendica, make it world readable and point your web browser to - http://yoursitenamehere.com/test.out +> http://yoursitenamehere.com/test.out This file should be blocked. You should get a permission denied message. @@ -376,9 +405,10 @@ If you do not see the word "test", your `.htaccess` is working, but it is likely that mod-rewrite is not installed in your web server or is not working. On most Linux flavors: - - % a2enmod rewrite - % /etc/init.d/apache2 restart +```sh +a2enmod rewrite +/etc/init.d/apache2 restart +``` Consult your hosting provider, experts on your particular Linux distribution or (if Windows) the provider of your Apache server software if you need to change @@ -391,15 +421,17 @@ distribution or Apache package (if using Windows). Create an empty `config/local.config.php`file and apply world-write permission. On Linux: - - % touch config/local.config.php - % chmod 664 config/local.config.php +```sh +touch config/local.config.php +chmod 664 config/local.config.php +``` Retry the installation. As soon as the database has been created, ******* this is important ********* - - % chmod 644 config/local.config.php +```sh +chmod 644 config/local.config.php +``` ### Suhosin issues @@ -436,7 +468,7 @@ provided by one of our members. > (attacker 'REMOTE_ADDR not set', file '/var/www/friendica/friendica/boot.php', > line 1341) > -> After a while I noticed, that `bin/console.php worker` calls further PHP script via `proc_open`. +> After a while I noticed, that `bin/console.php worker` calls further PHP scripts via `proc_open`. > These scripts themselves also use `proc_open` and fail, because they are NOT > called with `-d suhosin.executor.func.blacklist=none`. > @@ -457,12 +489,13 @@ provided by one of our members. If the setup fails to create all the database tables and/or manual creation from the command line fails, with this error: - ERROR 1067 (42000) at line XX: Invalid default value for 'created' +> ERROR 1067 (42000) at line XX: Invalid default value for 'created' You need to adjust your my.cnf and add the following setting under the [mysqld] section: - - sql_mode = ''; +``` +sql_mode = ''; +``` After that, restart mysql and try again. @@ -549,9 +582,11 @@ You may also set it manually in the config file or in the database within the `d Altering of a table may fail if it contains a large number of rows. First verify the existing timeout (50s by default): - -`show global variables like "innodb_lock_wait_timeout";` +```sql +show global variables like "innodb_lock_wait_timeout"; +``` Then increase it: - -`set global innodb_lock_wait_timeout=600;` +```sql +set global innodb_lock_wait_timeout=600; +``` diff --git a/doc/Installing-Connectors.md b/doc/en/admin/installing-connectors.md similarity index 92% rename from doc/Installing-Connectors.md rename to doc/en/admin/installing-connectors.md index bd564eb466..e59c717c44 100644 --- a/doc/Installing-Connectors.md +++ b/doc/en/admin/installing-connectors.md @@ -1,15 +1,11 @@ -Installing Connectors -================================================== - -* [Home](help) +# Installing Connectors Friendica uses add-ons to connect to some networks, such as Tumblr or Bluesky. 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. -Site configuration ---- +## Site configuration Addons need to be installed by the site administrator before they can be used. This is done through the site administration panel. @@ -20,8 +16,7 @@ Other connectors, such as Bluesky, 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 ---- +## Bluesky Jetstream To further improve connectivity to Bluesky, Admins can choose to enable 'Jetstream' connectivity. Jetstream is a service that connects to the Bluesky firehose. diff --git a/doc/Migrate.md b/doc/en/admin/migrate.md similarity index 98% rename from doc/Migrate.md rename to doc/en/admin/migrate.md index ca0e0d0d95..2b85c47255 100644 --- a/doc/Migrate.md +++ b/doc/en/admin/migrate.md @@ -1,7 +1,4 @@ -Migrating to a new server installation -=============== - -* [Home](help) +# Migrating to a new server installation ## Preparation @@ -39,9 +36,9 @@ Before transferring your database, you may want to clean it up; ensure the expir After adjusting these settings, the database cleaning up processes will be initiated according to your configured daily cron job. To review the size of your database, log into MySQL with ``mysql -p`` run the following query: -```` +```sql SELECT table_schema AS "Database", SUM(data_length + index_length) / 1024 / 1024 / 1024 AS "Size (GB)" FROM information_schema.TABLES GROUP BY table_schema; -```` +``` You should see an output like this: ```` @@ -89,4 +86,3 @@ If you are unable to login to your newly migrated Friendica installation, check If still unable to resolve the problem, it's likely an issue with your [installation](Install). In this case, you may try to an entirely new Friendica installation on your new server, but use a different FQDN and DNS name. Once you have this up and running, take it offline and purge the database and configuration file and try migrating to this installation. - diff --git a/doc/stats.md b/doc/en/admin/monitoring.md similarity index 96% rename from doc/stats.md rename to doc/en/admin/monitoring.md index 1b6a2dfd2a..5be827a2f3 100644 --- a/doc/stats.md +++ b/doc/en/admin/monitoring.md @@ -1,7 +1,4 @@ -Monitoring -=========== - -* [Home](help) +# Monitoring ## Endpoints diff --git a/doc/Settings.md b/doc/en/admin/settings.md similarity index 95% rename from doc/Settings.md rename to doc/en/admin/settings.md index 7ca0e22286..3c208f5542 100644 --- a/doc/Settings.md +++ b/doc/en/admin/settings.md @@ -1,7 +1,5 @@ # Settings -* [Home](help) - If you are the admin of a Friendica node, you have access to the **Admin Panel** where you can configure your Friendica node. ## Overview @@ -48,17 +46,16 @@ It is used as fall back setting should Friendica fail to recognize the visitors The Friendica community offers some translations. Some more complete then others. -See [this help page](/help/translations) for more information about the translation process. +See [this help page](/help/developer/translations) for more information about the translation process. #### System Theme Choose a theme to be the default system theme. This can be over-ridden by user profiles. -Default theme is `vier` at the moment. +Default theme is `frio` at the moment. You may also want to set a special theme for mobile interfaces. -Which may or may not be necessary depending of the mobile friendliness of the desktop theme you have chosen. -The `vier` theme for instance is mobile friendly. +It may or may not be necessary depending of the mobile friendliness of the desktop theme you have chosen. ### Registration @@ -74,7 +71,7 @@ You can chose between the following modes: ##### Invitation based registry Additionally to the setting in the admin panel, you can decide if registrations are only possible using an invitation code or not. -To enable invitation based registration, you have to set the `invitation_only` setting to `true` in the `system` section of the [config/local.config.php](/help/Config) file. +To enable invitation based registration, you have to set the `invitation_only` setting to `true` in the `system` section of the [config/local.config.php](/help/admin/config) file. If you want to use this method, the registration policy has to be set to either *open* or *requires approval*. #### Check Display Names @@ -114,7 +111,7 @@ If you use those, please refer to the documentation of those addons for further Default value is 'Database (legacy)': it's the legacy way used to store data directly in database. -Existing data can be moved to the current active backend using the ['storage move' console command](help/tools) +Existing data can be moved to the current active backend using the ['storage move' console command](help/admin/tools) If selected backend has configurable options, new fields are shown here. @@ -352,11 +349,12 @@ If you want to enable those, you have to activate them in the ``config/local.con Use the following settings to redirect PHP errors to a file. Config: - - error_reporting(E_ERROR | E_WARNING | E_PARSE ); - ini_set('error_log','php.out'); - ini_set('log_errors','1'); - ini_set('display_errors', '0'); +``` +error_reporting(E_ERROR | E_WARNING | E_PARSE ); +ini_set('error_log','php.out'); +ini_set('log_errors','1'); +ini_set('display_errors', '0'); +``` This will put all PHP errors in the file php.out (which must be writeable by the webserver). Undeclared variables are occasionally referenced in the program and therefore we do not recommend using `E_NOTICE` or `E_ALL`. @@ -383,14 +381,15 @@ These are the data base settings, the admin account settings, the path of PHP an ## DB Settings With the following settings, you specify the data base server, the username and password for Friendica and the database to use. - - 'database' => [ - 'hostname' => 'localhost', - 'username' => 'mysqlusername', - 'password' => 'mysqlpassword', - 'database' => 'mysqldatabasename', - 'charset' => 'utf8mb4', - ], +``` +'database' => [ + 'hostname' => 'localhost', + 'username' => 'mysqlusername', + 'password' => 'mysqlpassword', + 'database' => 'mysqldatabasename', + 'charset' => 'utf8mb4', +], +``` ## Admin users @@ -398,31 +397,33 @@ You can set one, or more, accounts to be *Admin*. By default this will be the one account you create during the installation process. But you can expand the list of email addresses by any used email address you want. Registration of new accounts with a listed email address is not possible. - - 'config' => [ - 'admin_email' => 'you@example.com, buddy@example.com', - ], +``` +'config' => [ + 'admin_email' => 'you@example.com, buddy@example.com', +], +``` ## PHP Path Some of Friendica's processes are running in the background. For this you need to specify the path to the PHP binary to be used. - - 'config' => [ - 'php_path' => '/usr/bin/php', - ], +``` +'config' => [ + 'php_path' => '/usr/bin/php', +], +``` ## Subdirectory configuration It is possible to install Friendica into a subdirectory of your web server. We strongly discourage you from doing so, as this will break federation to other networks (e.g. Diaspora, GNU Social, Hubzilla) Say you have a subdirectory for tests and put Friendica into a further subdirectory, the config would be: - - 'system' => [ - 'url' => 'https://example.com/tests/friendica', - ], +``` +'system' => [ + 'url' => 'https://example.com/tests/friendica', +], +``` ## Other exceptions -Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in config/local.config.php](help/Config) section of the documentation. - +Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in config/local.config.php](help/admin/config) section of the documentation. diff --git a/doc/SSL.md b/doc/en/admin/ssl.md similarity index 90% rename from doc/SSL.md rename to doc/en/admin/ssl.md index d3f5ecc895..e9fc01c76c 100644 --- a/doc/SSL.md +++ b/doc/en/admin/ssl.md @@ -1,7 +1,4 @@ -Using SSL with Friendica -===================================== - -* [Home](help) +# Using SSL with Friendica ## Disclaimer @@ -49,7 +46,7 @@ If you run your own server, we recommend to check out the ["Let's Encrypt" initi Not only do they offer free SSL certificates, but also a way to automate their renewal. You need to install a client software on your server to use it. Instructions for the official client are [here](https://certbot.eff.org/). -Depending on your needs, you might want to look at the [list of alternative letsencrypt clients](https://letsencrypt.org/docs/client-options/). +Depending on your needs, you might want to look at the [list of alternative LetsEncrypt clients](https://letsencrypt.org/docs/client-options/). ## Web server settings @@ -70,22 +67,26 @@ This is the simplest way to enforce site-wide secure access. Every time a user tries to access any Friendica page by any mean (manual address bar entry or link), the web server issues a Permanent Redirect response with the secure protocol prepended to the requested URL. With Apache, enable the modules rewrite and ssl (with a shared hosting provider, this should be enabled already): - - sudo a2enmod rewrite ssl +```sh +sudo a2enmod rewrite ssl +``` Add the following lines to the .htaccess file in the root folder of your Friendica instance (thanks to [AlfredSK](https://github.com/AlfredSK)): - RewriteEngine On - RewriteCond %{SERVER_PORT} 80 - RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] +``` +RewriteEngine On +RewriteCond %{SERVER_PORT} 80 +RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] +``` With nginx, configure your server directive this way ([documentation](https://www.nginx.com/blog/creating-nginx-rewrite-rules/)): - - server { - listen 80; - server_name your.friendica.domain; - return 301 https://$server_name$request_uri; - } +``` +server { + listen 80; + server_name your.friendica.domain; + return 301 https://$server_name$request_uri; +} +``` ### SSL Settings diff --git a/doc/tools.md b/doc/en/admin/tools.md similarity index 88% rename from doc/tools.md rename to doc/en/admin/tools.md index fac1f4b392..4e4c734b6b 100644 --- a/doc/tools.md +++ b/doc/en/admin/tools.md @@ -1,10 +1,6 @@ -Admin Tools -=========== +# Admin tools -* [Home](help) - -Friendica Tools ---------------- +## Friendica tools Friendica has a build in command console you can find in the *bin* directory. The console provides the following commands: @@ -31,8 +27,7 @@ The console provides the following commands: Please consult *bin/console help* on the command line interface of your server for details about the commands. -3rd Party Tools ---------------- +## 3rd Party Tools In addition to the tools Friendica includes, some 3rd party tools can make your admin days easier. @@ -44,21 +39,23 @@ The following configuration was [provided](https://forum.friendi.ca/display/1745 You need to adjust the *logpath* in the *jail.local* file and the *bantime* (value is in seconds). In */etc/fail2ban/jail.local* create a section for Friendica: - - [friendica] - enabled = true - findtime = 300 - bantime = 900 - filter = friendica - port = http,https - logpath = /var/log/friendica.log - logencoding = utf-8 +```toml +[friendica] +enabled = true +findtime = 300 +bantime = 900 +filter = friendica +port = http,https +logpath = /var/log/friendica.log +logencoding = utf-8 +``` And create a filter definition in */etc/fail2ban/filter.d/friendica.conf*: - - [Definition] - failregex = ^.*authenticate\: failed login attempt.*\"ip\"\:\"\".*$ - ignoreregex = +```toml +[Definition] +failregex = ^.*authenticate\: failed login attempt.*\"ip\"\:\"\".*$ +ignoreregex = +``` Additionally you have to define the number of failed logins before the ban should be activated. This is done either in the global configuration or for each jail separately. @@ -73,8 +70,10 @@ To keep them in control you should add them to the automatic [log rotation](http In */etc/logrotate.d/* add a file called *friendica* that contains the configuration. The following will compress */var/log/friendica* (assuming this is the location of the log file) on a daily basis and keep 2 days of back-log. - /var/log/friendica.log { - compress - daily - rotate 2 - } +``` +/var/log/friendica.log { + compress + daily + rotate 2 +} +``` diff --git a/doc/Update.md b/doc/en/admin/update.md similarity index 91% rename from doc/Update.md rename to doc/en/admin/update.md index b6c5c53e19..b7941267c3 100644 --- a/doc/Update.md +++ b/doc/en/admin/update.md @@ -1,7 +1,4 @@ -Updating Friendica -=============== - -* [Home](help) +# Updating Friendica ## Using a Friendica archive @@ -27,15 +24,17 @@ To update Addons from an archive, simply delete the ``path/to/friendica/addon`` ## Using Git You can get the latest changes at any time with - - cd path/to/friendica - git pull - bin/composer.phar run install:prod +```sh +cd path/to/friendica +git pull +bin/composer.phar run install:prod +``` The addon tree has to be updated separately like so: - - cd path/to/friendica/addon - git pull +```sh +cd path/to/friendica/addon +git pull +``` For both repositories: The default branch to use is the ``stable`` branch, which is the stable version of Friendica. @@ -61,7 +60,7 @@ There are two main ways of doing it, either by manually removing the duplicates Manually removing the duplicates is usually faster if they're not too numerous. To manually remove the duplicates, you need to know the UNIQUE index columns available in `database.sql`. -```SQL +```sql SELECT GROUP_CONCAT(id), , count(*) as count FROM users GROUP BY HAVING count >= 2; @@ -71,7 +70,7 @@ GROUP BY HAVING count >= 2; If there are too many rows to handle manually, you can create a new table with the same structure as the table with duplicates and insert the existing content with INSERT IGNORE. To recreate the table you need to know the table structure available in `database.sql`. -```SQL +```sql CREATE TABLE _new ; INSERT IGNORE INTO _new SELECT * FROM ; DROP TABLE ; @@ -84,7 +83,7 @@ This method is slower overall, but it is better suited for large numbers of dupl #### Foreign Keys -Some of the updates include the use of foreign keys now that will bump into issues with previous versions, which would sometimes shove bad data into tables, preventing, causing errors such as below. +Some updates include the use of foreign keys now that will bump into issues with previous versions, which would sometimes shove bad data into tables, preventing, causing errors such as below. ``` Error 1452 occurred during database update: @@ -94,7 +93,7 @@ ALTER TABLE `thread` ADD FOREIGN KEY (`iid`) REFERENCES `item` (`id`) ON UPDATE All current known fixes for possible items that can go wrong are as below. -```SQL +```sql DELETE FROM `item` WHERE `owner-id` NOT IN (SELECT `id` FROM `contact`); DELETE FROM `item` WHERE `contact-id` NOT IN (SELECT `id` FROM `contact`); DELETE FROM `notify` WHERE `uri-id` NOT IN (SELECT `id` FROM `item-uri`); diff --git a/doc/Addons.md b/doc/en/developer/addon-development.md similarity index 98% rename from doc/Addons.md rename to doc/en/developer/addon-development.md index 84586f91e2..9bc0c878e6 100644 --- a/doc/Addons.md +++ b/doc/en/developer/addon-development.md @@ -1,7 +1,4 @@ -Friendica Addon development -============== - -* [Home](help) +# Friendica addon development Please see the sample addon 'randplace' for a working example of using some of these features. Addons work by intercepting event hooks - which must be registered. @@ -144,7 +141,7 @@ No additional data is provided. ## Modules Addons may also act as "modules" and intercept all page requests for a given URL path. -In order for a addon to act as a module it needs to declare an empty function `_module()`. +In order for an addon to act as a module it needs to declare an empty function `_module()`. If this function exists, you will now receive all page requests for `https://my.web.site/` - with any number of URL components as additional arguments. These are parsed into the `App\Arguments` object. @@ -560,7 +557,7 @@ For `select`, **field** is: Called just before dispatching the router. Hook data is a `\FastRoute\RouterCollector` object that should be used to add addon routes pointing to classes. -**Notice**: The class whose name is provided in the route handler must be reachable via auto-loader. +**Notice**: The class whose name is provided in the route handler must be reachable via autoloader. ### probe_detect @@ -618,7 +615,7 @@ Called when unfollowing a remote contact on a non-native network (like Bluesky) Hook data: - **contact** (input): the target public contact (uid = 0) array. - **uid** (input): the id of the source local user. -- **result** (output): wether the unfollowing is successful or not. +- **result** (output): whether the unfollowing is successful or not. ### revoke_follow @@ -627,7 +624,7 @@ Called when making a remote contact on a non-native network (like Bluesky) unfol Hook data: - **contact** (input): the target public contact (uid = 0) array. - **uid** (input): the id of the source local user. -- **result** (output): a boolean value indicating wether the operation was successful or not. +- **result** (output): a boolean value indicating whether the operation was successful or not. ### block @@ -636,7 +633,7 @@ Called when blocking a remote contact on a non-native network (like Bluesky). Hook data: - **contact** (input): the remote contact (uid = 0) array. - **uid** (input): the user id to issue the block for. -- **result** (output): a boolean value indicating wether the operation was successful or not. +- **result** (output): a boolean value indicating whether the operation was successful or not. ### unblock @@ -645,7 +642,7 @@ Called when unblocking a remote contact on a non-native network (like Bluesky). Hook data: - **contact** (input): the remote contact (uid = 0) array. - **uid** (input): the user id to revoke the block for. -- **result** (output): a boolean value indicating wether the operation was successful or not. +- **result** (output): a boolean value indicating whether the operation was successful or not. ### support_probe diff --git a/doc/AddonStorageBackend.md b/doc/en/developer/addon-storage-backend.md similarity index 99% rename from doc/AddonStorageBackend.md rename to doc/en/developer/addon-storage-backend.md index 5053b641cb..63ef814bd6 100644 --- a/doc/AddonStorageBackend.md +++ b/doc/en/developer/addon-storage-backend.md @@ -1,7 +1,4 @@ -Friendica Storage Backend Addon development -=========================================== - -* [Home](help) +# Friendica storage backend addon development Storage backends can be added via addons. A storage backend is implemented as a class, and the plugin register the class to make it available to the system. diff --git a/doc/autoloader.md b/doc/en/developer/autoloader.md similarity index 90% rename from doc/autoloader.md rename to doc/en/developer/autoloader.md index 5bc0bfe9b3..92c26b2158 100644 --- a/doc/autoloader.md +++ b/doc/en/developer/autoloader.md @@ -1,16 +1,14 @@ -Autoloader with Composer -========== +# Autoloader with Composer -* [Home](help) - * [Developer Intro](help/Developers-Intro) +* [Developer Intro](help/developer/index) Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes. It's a command-line tool that downloads required libraries into the `vendor` folder and makes any namespaced class in `src` available through the whole application. -* [Using Composer](help/Composer) +* [Using Composer](help/developer/composer) -## A quick introduction to class autoloading +## A quick introduction to class auto-loading The autoloader dynamically includes the file defining a class when it is first referenced, either by instantiating an object or simply making sure that it is available, without the need to explicitly use "require_once". @@ -87,7 +85,7 @@ class ItemsManager extends BaseManager { ``` Even though we didn't explicitly include the `src/BaseManager.php` file, the autoloader will when this class is first defined, because it is referenced as a parent class. -It works with the "BaseManager" example here and it works when we need to call static methods: +It works with the "BaseManager" example here, and it works when we need to call static methods: ```php // src/Dfrn.php @@ -153,7 +151,7 @@ class Diaspora { } ``` -if you use that class in many places of the code and you don't want to write the full path to the class every time, you can use the "use" PHP keyword +if you use that class in many places of the code, and you don't want to write the full path to the class every time, you can use the "use" PHP keyword ```php // src/Diaspora.php @@ -198,5 +196,5 @@ So you can think of namespaces as folders in a Unix file system, with global sco ## Related -* [Using Composer](help/Composer) -* [How To Move Classes to `src`](help/Developer-How-To-Move-Classes-to-src) +* [Using Composer](help/developer/composer) +* [How To Move Classes to `src`](help/developer/how-to-move-classes-to-src) diff --git a/doc/Composer.md b/doc/en/developer/composer.md similarity index 90% rename from doc/Composer.md rename to doc/en/developer/composer.md index 7310a443eb..64a7a7e9d7 100644 --- a/doc/Composer.md +++ b/doc/en/developer/composer.md @@ -1,14 +1,12 @@ -Using Composer -============== +# Using Composer -* [Home](help) - * [Developer Intro](help/Developers-Intro) +* [Developer Intro](help/developer/index) Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes. It's a command-line tool that downloads required libraries into the `vendor` folder and makes any namespaced class in `src` available through the whole application. -* [Class autoloading](help/autoloader) +* [Class autoloading](help/developer/autoloader) ## How to use Composer @@ -55,8 +53,8 @@ If you don't need to use any third-party library, then you don't need to use Com #### Adding a third-party library to Friendica -Does your shiny new [Addon](help/Addons) need to rely on a third-party library not required by Friendica yet? -First of all, this library should be available on [Packagist](https://packagist.org) so that Composer knows how to fetch it directly just by mentioning its name in `composer.json`. +Does your shiny new [Addon](help/developer/addon-development) need to rely on a third-party library not required by Friendica yet? +First, this library should be available on [Packagist](https://packagist.org) so that Composer knows how to fetch it directly just by mentioning its name in `composer.json`. This file is the configuration of Friendica for Composer. It lists details about the Friendica project, but also a list of required dependencies and their target version. Here's a simplified version of the one we currently use on Friendica: @@ -116,5 +114,5 @@ $> COMPOSER_HOME=/var/tmp/composer sudo -u [web user] bin/composer.phar [mode] ## Related -* [Class autoloading](help/autoloader) -* [How To Move Classes to `src`](help/Developer-How-To-Move-Classes-to-src) +* [Class autoloading](help/developer/autoloader) +* [How To Move Classes to `src`](help/developer/developer-how-to-move-classes-to-src) diff --git a/doc/Developer-Domain-Driven-Design.md b/doc/en/developer/domain-driven-design.md similarity index 96% rename from doc/Developer-Domain-Driven-Design.md rename to doc/en/developer/domain-driven-design.md index 3052074443..d43c3417d5 100644 --- a/doc/Developer-Domain-Driven-Design.md +++ b/doc/en/developer/domain-driven-design.md @@ -1,8 +1,6 @@ -Domain-Driven-Design -============== +# Domain-driven design -* [Home](help) - * [Developer Intro](help/Developers-Intro) +* [Developer Intro](help/developer/index) Friendica uses class structures inspired by Domain-Driven-Design programming patterns. This page is meant to explain what it means in practical terms for Friendica development. @@ -85,7 +83,7 @@ class Model { $this->dba = $dba; } - + function save() { return $this->dba->update('table', get_object_vars($this), ['id' => $this->id]); @@ -136,7 +134,7 @@ class Factory public function create() { - return new Model($this->dba); + return new Model($this->dba); } } @@ -170,7 +168,7 @@ class Model { $this->dba = $dba; } - + function save() { return $this->dba->update('table', get_object_vars($this), ['id' => $this->id]); @@ -191,7 +189,7 @@ class Factory public function create() { - return new Model($this->dba); + return new Model($this->dba); } } @@ -223,7 +221,7 @@ class Repository extends Factory public function create() { - return new Model($this->dba); + return new Model($this->dba); } public function save(Model $model) diff --git a/doc/GitHub.md b/doc/en/developer/github.md similarity index 88% rename from doc/GitHub.md rename to doc/en/developer/github.md index 24f2e6aa41..4cc6d45bea 100644 --- a/doc/GitHub.md +++ b/doc/en/developer/github.md @@ -1,12 +1,8 @@ -Friendica on GitHub -=================== - -* [Home](help) +# Friendica on GitHub Here is how you can work on the code with us. If you have any questions please write to the Friendica developers' group. -Introduction to the workflow with our GitHub repository -------------------------------------------------------- +## Introduction to the workflow with our GitHub repository 1. Install git on the system you will be developing on. 2. Create your own [GitHub](https://github.com) account. @@ -17,8 +13,7 @@ Follow the instructions provided here: [http://help.github.com/fork-a-repo/](htt 6. Commit your changes to your fork. Then go to your GitHub page and create a "Pull request" to notify us to merge your work. -Our Git Branches ----------------- +## Our Git Branches There are two relevant branches in the main repo on GitHub: @@ -26,8 +21,7 @@ There are two relevant branches in the main repo on GitHub: 2. develop: This branch contains the latest code. This is what you want to work with. -Fast-forwarding ---------------- +## Fast-forwarding Fast forwarding is enabled by default in git. When you merge with fast-forwarding it does not add a new commit to mark when you've performed the merge and how. @@ -37,8 +31,7 @@ This is done by running "git merge --no-ff". [Here](https://stackoverflow.com/questions/5519007/how-do-i-make-git-merges-default-be-no-ff-no-commit) is an explanation on how to configure git to turn off fast-forwarding by default. You can find some more background reading [here](http://nvie.com/posts/a-successful-git-branching-model/). -Release branches ----------------- +## Release branches A release branch is created when the develop branch contains all features it should have. A release branch is used for a few things. @@ -55,8 +48,7 @@ If you were to merge develop into release-3.4 at this point, features and bug-fi This might introduce new bugs, too. Which defeats the purpose of the release branch. -Some important reminders ------------------------- +## Some important reminders 1. Please pull in any changes from the project repository and merge them with your work **before** issuing a pull request. We reserve the right to reject any patch which results in a large number of merge conflicts. @@ -69,8 +61,9 @@ Don't hesitate to ask us in case of doubt. 3. Check your code for typos. There is a console command called *typo* for this. +```sh +php bin/console.php typo +``` - $> php bin/console.php typo - -Check out how to work with [our Vagrant](help/Vagrant) to save a lot of setup time! +Check out how to work with [our Vagrant](help/developer/vagrant) to save a lot of setup time! diff --git a/doc/Developer-How-To-Move-Classes-to-src.md b/doc/en/developer/how-to-move-classes-to-src.md similarity index 90% rename from doc/Developer-How-To-Move-Classes-to-src.md rename to doc/en/developer/how-to-move-classes-to-src.md index c33df3d729..22e6bf9d33 100644 --- a/doc/Developer-How-To-Move-Classes-to-src.md +++ b/doc/en/developer/how-to-move-classes-to-src.md @@ -1,18 +1,16 @@ -How To Move Classes to `src` -============== +# How to move classes to `src` -* [Home](help) - * [Developer Intro](help/Developers-Intro) +* [Developer Intro](help/developer/index) -Friendica uses [Composer](help/Composer) to manage autoloading. -This means that all the PHP class files moved to the `src` folder will be [automatically included](help/autoloader) when the class it defines is first used in the flow. +Friendica uses [Composer](help/developer/composer) to manage autoloading. +This means that all the PHP class files moved to the `src` folder will be [automatically included](help/developer/autoloader) when the class it defines is first used in the flow. This is an improvement over the current `require` usage since files will be included on an actual usage basis instead of the presence of a `require` call. However, there are a significant number of items to check when moving a class file from the `include` folder to the `src` folder, and this page is there to list them. ## Decide the namespace -This isn't the most technical decision of them all, but it has long lasting consequences as it will be the name that will be used to refer to this class from now on. +This isn't the most technical decision of them all, but it has long-lasting consequences as it will be the name that will be used to refer to this class from now on. There is [a shared Ethercalc sheet](https://ethercalc.org/friendica_classes) to suggest namespace/class names that lists all the already moved class files for inspiration. A few pointers though: @@ -34,7 +32,7 @@ namespace Friendica\Core; From now on, the `Config` class can be referred to as `Friendica\Core\Config`, however it isn't very practical, especially when the class was previously used as `Config`. Thankfully, PHP provides namespace shortcuts through `use`. -This language construct just provides a different naming scheme for a namespace or a class, but doesn't trigger the autoload mechanism on its own. +This language construct just provides a different naming scheme for a namespace or a class, but doesn't trigger the autoload-mechanism on its own. Here are the different ways you can use `use`: ````php @@ -104,5 +102,5 @@ Most of the time it's used for debugging purposes but there can be instances whe ## Related -* [Class autoloading](help/autoloader) -* [Using Composer](help/Composer) \ No newline at end of file +* [Class autoloading](help/developer/autoloader) +* [Using Composer](help/developer/composer) diff --git a/doc/Developers-Intro.md b/doc/en/developer/index.md similarity index 96% rename from doc/Developers-Intro.md rename to doc/en/developer/index.md index 5dbf1def4a..ed8cbc4e5b 100644 --- a/doc/Developers-Intro.md +++ b/doc/en/developer/index.md @@ -2,11 +2,9 @@ -* [Home](help) - Do you want to help us improve Friendica? Here we have compiled some hints on how to get started and some tasks to help you choose. -A project like Friendica is the sum of many different contributions. +A project like Friendica is the sum of many contributions. **Very different skills are required to make good software, not all of them involve coding!** We are looking for helpers in all areas, whether you write text or code, whether you spread the word to convince people or design new icons. Whether you feel like an expert or like a newbie - join us with your ideas! @@ -25,7 +23,7 @@ Welcome them, answer their questions, point them to documentation or ping other ## Translation -The documentation contains help on how to translate Friendica [at Transifex](/help/translations) where the UI is translated. +The documentation contains help on how to translate Friendica [at Transifex](/help/developer/translations) where the UI is translated. If you don't want to translate the UI, or it is already done to your satisfaction, you might want to work on the translation of the /help files? ## Design @@ -41,7 +39,7 @@ If you have seen Friendica you probably have ideas to improve it, haven't you? ## Programming -Friendica uses an implementation of [Domain-Driven-Design](help/Developer-Domain-Driven-Design), please make sure to check out the provided links for hints at the expected code architecture. +Friendica uses an implementation of [Domain-Driven-Design](help/developer/domain-driven-design), please make sure to check out the provided links for hints at the expected code architecture. ### Composer @@ -66,9 +64,9 @@ If you want to have git automatically update the dependencies with composer, you just place it into `.git/hooks/post-merge` and make it executable. -* [Class autoloading](help/autoloader) -* [Using Composer](help/Composer) -* [How To Move Classes to `src`](help/Developer-How-To-Move-Classes-to-src) +* [Class autoloading](help/developer/autoloader) +* [Using Composer](help/developer/composer) +* [How To Move Classes to `src`](help/developer/how-to-move-classes-to-src) ### Coding standards @@ -148,7 +146,7 @@ If you want to get involved here: ### Client software -As Friendica is using a [Twitter/GNU Social compatible API](help/api) any of the clients for those platforms should work with Friendica as well. +As Friendica is using a [Twitter/GNU Social compatible API](help/spec/api/index) any of the clients for those platforms should work with Friendica as well. Furthermore, there are several client projects, especially for use with Friendica. If you are interested in improving those clients, please contact the developers of the clients directly. diff --git a/doc/smarty3-templates.md b/doc/en/developer/smarty3-templates.md similarity index 85% rename from doc/smarty3-templates.md rename to doc/en/developer/smarty3-templates.md index 0fbe503ebf..44776d50c4 100644 --- a/doc/smarty3-templates.md +++ b/doc/en/developer/smarty3-templates.md @@ -1,7 +1,4 @@ -Friendica Templating Documentation -================================== - -* [Home](help) +# Friendica templating documentation Friendica uses [Smarty 3](http://www.smarty.net/) as PHP templating engine. The main templates are found in @@ -21,25 +18,27 @@ Templates that are only used by addons shall be placed in the directory. To render a template use the function *getMarkupTemplate* to load the template and *replaceMacros* to replace the macros/variables in the just loaded template file. - - $tpl = Renderer::getMarkupTemplate('install_settings.tpl'); - $o .= Renderer::replaceMacros($tpl, array( ... )); +```php +$tpl = Renderer::getMarkupTemplate('install_settings.tpl'); +$o .= Renderer::replaceMacros($tpl, array( ... )); +``` the array consists of an association of an identifier and the value for that identifier, i.e. - - '$title' => $install_title, +```php +'$title' => $install_title, +``` where the value may as well be an array by its own. -Form Templates --------------- +## Form Templates To guarantee a consistent look and feel for input forms, i.e. in the settings sections, there are templates for the basic form fields. -They are initialized with an array of data, depending on the tyle of the field. +They are initialized with an array of data, depending on the style of the field. All of these take an array holding the values, e.g. for a one line text input field, which is required and should be used to type email addresses use something along the lines of: - - '$adminmail' => array('adminmail', DI::l10n()->t('Site administrator email address'), $adminmail, DI::l10n()->t('Your account email address must match this in order to use the web admin panel.'), 'required', '', 'email'), +```php +'$adminmail' => array('adminmail', DI::l10n()->t('Site administrator email address'), $adminmail, DI::l10n()->t('Your account email address must match this in order to use the web admin panel.'), 'required', '', 'email'), +``` To evaluate the input value, you can then use the $_POST array, more precisely the $_POST['adminemail'] variable. @@ -148,25 +147,25 @@ Field parameter: ### field_select.tpl -A drop down selection box. +A drop-down selection box. Field parameter: 0. Name of the field, 1. Label of the selection box, 2. Current selected value, 3. Help text for the selection box, -4. Array holding the possible values of the selection drop down. +4. Array holding the possible values of the selection drop-down. ### field_select_raw.tpl -A drop down selection box (see above) but you have to prepare the values yourself. +A drop-down selection box (see above) but you have to prepare the values yourself. Field parameter: 0. Name of the field, 1. Label of the selection box, 2. Current selected value, 3. Help text for the selection box, -4. Possible values of the selection drop down. +4. Possible values of the selection drop-down. ### field_textarea.tpl diff --git a/doc/StrategyHooks.md b/doc/en/developer/strategy-hooks.md similarity index 97% rename from doc/StrategyHooks.md rename to doc/en/developer/strategy-hooks.md index 3382f7e494..1e6bf1090b 100644 --- a/doc/StrategyHooks.md +++ b/doc/en/developer/strategy-hooks.md @@ -1,7 +1,4 @@ -Friendica strategy Hooks -=========================================== - -* [Home](help) +# Friendica strategy Hooks ## Strategy hooks diff --git a/doc/Tests.md b/doc/en/developer/tests.md similarity index 93% rename from doc/Tests.md rename to doc/en/developer/tests.md index 6acb4e783a..a2b9137863 100644 --- a/doc/Tests.md +++ b/doc/en/developer/tests.md @@ -1,6 +1,4 @@ -# Themes - -* [Home](help) +# Tests You can run unit tests with [PHPUnit](https://phpunit.de/): diff --git a/doc/translations.md b/doc/en/developer/translations.md similarity index 93% rename from doc/translations.md rename to doc/en/developer/translations.md index 4c84b67a81..d5865c3ad2 100644 --- a/doc/translations.md +++ b/doc/en/developer/translations.md @@ -1,7 +1,4 @@ -Friendica translations -====================== - -* [Home](help) +# Friendica translations ## Overview @@ -30,7 +27,7 @@ We currently support the gettext version 0.19.8.1 and actively check new transla If you don't use this version, it's possible that our checks fail (f.e. because of tiny differences at linebreaks). In case you do have a Docker environment, you can easily update the translations with the following command: -```shell +```sh docker run --rm -v $PWD:/data -w /data friendicaci/transifex bin/run_xgettext.sh ``` @@ -43,9 +40,10 @@ Once you have added new translation strings in your code changes, please run `bi If you have the `friendica-addons` repository in the `addon` directory of your Friendica cloned repository, just run `bin/run_xgettext.sh -a ` from the base Friendica directory. Otherwise: - - cd /path/to/friendica-addons/ - /path/to/friendica/bin/run_xgettext.sh -s +```sh +cd /path/to/friendica-addons/ +/path/to/friendica/bin/run_xgettext.sh -s +``` In either case, you need to commit the updated `/lang/C/messages.po` to your working branch. @@ -65,17 +63,19 @@ After installation of the client, you should have a `tx` command available on yo To use it, first create a configuration file with your credentials. On Linux this file should be placed into your home directory `~/.transifexrc`. The content of the file should be something like the following: - - [https://app.transifex.com] - username = user - token = - password = p@ssw0rd - hostname = https://app.transifex.com +```toml +[https://app.transifex.com] +username = user +token = +password = p@ssw0rd +hostname = https://app.transifex.com +``` Since Friendica version 3.5.1 we ship configuration files for the Transifex client in the core repository and the addon repository in `.tx/config`. To update the PO files after you have translated strings of e.g. Esperanto on the Transifex website you can use `tx` to download the updated PO file in the right location. - - $> tx pull -l eo +```sh +tx pull -l eo +``` Then run `bin/console po2php view/lang//messages.po` to update the related `strings.php` file and commit both files to your working branch. diff --git a/doc/Vagrant.md b/doc/en/developer/vagrant.md similarity index 80% rename from doc/Vagrant.md rename to doc/en/developer/vagrant.md index 29a2871bd8..f59b99c69f 100644 --- a/doc/Vagrant.md +++ b/doc/en/developer/vagrant.md @@ -1,16 +1,12 @@ -Vagrant for Friendica Developers -=================== +# Vagrant for Friendica developers -* [Home](help) - -Getting started ---------------- +## Getting started [Vagrant](https://www.vagrantup.com/) is a virtualization solution for developers. No need to setup up a webserver, database etc. before actually starting. Vagrant creates a virtual machine for you that you can just run inside VirtualBox and start to work directly on Friendica. -It brings an Debian Bullseye with PHP 8.0 and MariaDB 10.5.11. +It brings a Debian Bullseye with PHP 8.0 and MariaDB 10.5.11. What you need to do: @@ -34,22 +30,24 @@ Find the Friendica log file `/vagrant/logfile.out` on the VM or in the `logfile. 8. Commit and push your changes directly back to GitHub. If you want to stop vagrant after finishing your work, run the following command - - $> vagrant halt +```sh +vagrant halt +``` in the development directory. This will not delete the virtual machine. 9. To ultimately delete the virtual machine run - - $> vagrant destroy - $> rm /vagrant/config/local.config.php +```sh +vagrant destroy +rm /vagrant/config/local.config.php +``` to make sure that you can start from scratch with another "vagrant up". Default User Accounts --------------------- -By default the provision script will setup two user accounts. +By default the provision script will set up two user accounts. * admin, password admin * friendica, password friendica @@ -57,10 +55,11 @@ By default the provision script will setup two user accounts. Trouble Shooting ---------------- -If you see a version mis-match for the _VirtualBox Guest Additions_ between host and guest during the initial setup of the Vagrant VM, you will need to install an addon to Vagrant (ref. [Stack Overflow](https://stackoverflow.com/a/38010683)). +If you see a version mismatch for the _VirtualBox Guest Additions_ between host and guest during the initial setup of the Vagrant VM, you will need to install an addon to Vagrant (ref. [Stack Overflow](https://stackoverflow.com/a/38010683)). Stop the Vagrant VM and run the following command: - - $> vagrant plugin install vagrant-vbguest +```sh +vagrant plugin install vagrant-vbguest +``` On the next Vagrant up, the version problem should be fixed. diff --git a/doc/en/home.md b/doc/en/home.md new file mode 100644 index 0000000000..d2e715a08c --- /dev/null +++ b/doc/en/home.md @@ -0,0 +1,81 @@ +# Help + +## User Manual + +* General functions - first steps + * [Account basics](help/user/account-basics) + * [Quick start for new users](help/user/quick-start/guide) + * [Creating posts](help/user/text-editor) + * [BBCode tag reference](help/user/bbcode) + * [Comment, sort and delete posts](help/user/text-comment) + * [Accesskey reference](help/user/access-keys) + * [Events](help/user/events) + * [Themes](help/user/themes) +* You and other users + * [Connectors](help/user/connectors) + * [Making friends](help/user/making-friends) + * [Safety](help/user/safety) + * [Circles and privacy](help/user/circles-and-privacy) + * [Tags and mentions](help/user/tags-and-mentions) + * [Account types: Groups and Pages](help/user/accounts-groups-pages) + * [Channels](help/user/channels) + * [Chats](help/user/chats) +* Further information + * [Frequently asked questions (FAQ)](help/user/faq) + * [Moving an account](help/user/move-account) + * [Export / Import of followed Contacts](help/user/export-import-contacts) + * [Deleting an account](help/user/delete-account) + * [Bugs and issues](help/user/bugs-and-issues) + +## Admin Manual + +* [Installation](help/admin/install) +* [Updating](help/admin/update) +* [Frequently asked questions (FAQ)](help/admin/faq) +* [Settings & Admin Panel](help/admin/settings) +* [Installing Connectors](help/admin/installing-connectors) +* [Installing an ejabberd server (XMPP chat) with synchronized credentials](help/admin/install-ejabberd) +* [Using SSL with Friendica](help/admin/ssl) +* [Config values that can only be set in config/local.config.php](help/admin/config) +* [Improving performance](help/admin/improve-performance) +* [Migrating to a new server](help/admin/migrate) +* [Administration tools](help/admin/tools) +* [Monitoring](help/admin/monitoring) + +## Developer Manual + +* [Get started](help/developer/index) +* Set up development environment + * [On GitHub](help/developer/github) + * [On Vagrant](help/developer/vagrant) +* Code structure + * [Domain-driven design](help/developer/domain-driven-design) + * [Addon development](help/developer/addon-development) + * [Smarty 3 templates](help/developer/smarty3-templates) + * [Storage backend addon](help/developer/addon-storage-backend) +* How To + * [Translating Friendica](help/developer/translations) + * [Using Composer](help/developer/composer) + * [Moving classes to the src directory](help/developer/how-to-move-classes-to-src) + * [Run tests](help/developer/tests) +* Reference + * [API endpoints](help/spec/api/index) + * [Code (Doxygen generated - sets cookies)](doc/html/) + * [Protocol documentation](help/spec/protocol/protocol) + * [Database schema documentation](help/spec/database/index) + * [Class autoloading](help/developer/autoloader) + +## Links + +* Website: [https://friendi.ca](https://friendi.ca) +* Help Group: [@helpers@forum.friendi.ca](https://forum.friendi.ca/~helpers) +* XMPP: [support@forum.friendi.ca](xmpp:support@forum.friendi.ca?join) +* IRC: [https://web.libera.chat/?channels=#friendica](https://web.libera.chat/?channels=#friendica) +* Matrix: [https://matrix.to/#/#friendi.ca:matrix.org](https://matrix.to/#/#friendi.ca:matrix.org) +* Mailing list: [https://mailman.friendi.ca/mailman/listinfo/support-friendi.ca](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) + +## About + +* [Server information](friendica) +* [Terms of service](tos) +* [Credits](credits) diff --git a/doc/API-Entities.md b/doc/en/spec/api/entities.md similarity index 93% rename from doc/API-Entities.md rename to doc/en/spec/api/entities.md index de3eac9b9a..93958a32f6 100644 --- a/doc/API-Entities.md +++ b/doc/en/spec/api/entities.md @@ -1,7 +1,7 @@ # Friendica API entities * [Home](help) - * [Using the APIs](help/api) + * [Using the APIs](help/spec/api/index) ## Activities @@ -18,31 +18,31 @@ like -List of Contacts +List of Contacts No dislike -List of Contacts +List of Contacts No attendyes -List of Contacts +List of Contacts No attendno -List of Contacts +List of Contacts No attendmaybe -List of Contacts +List of Contacts No @@ -330,31 +330,31 @@ Ex: Wed May 23 06:01:13 +0000 2007 hashtags -List of Hashtags +List of Hashtags No symbols -List of Symbols +List of Symbols No urls -List of URLs +List of URLs No user_mentions -List of User mentions +List of User mentions No media -List of Medias +List of Medias No @@ -570,13 +570,13 @@ Ex: Wed May 23 06:01:13 +0000 2007 user -Contact +Contact No friendica_author -Contact +Contact No @@ -584,7 +584,7 @@ Ex: Wed May 23 06:01:13 +0000 2007 friendica_owner -Contact +Contact No @@ -614,7 +614,7 @@ Ex: Wed May 23 06:01:13 +0000 2007 friendica_activities -Activities +Activities No @@ -632,13 +632,13 @@ Ex: Wed May 23 06:01:13 +0000 2007 attachments -List of Attachments +List of Attachments Yes entities -Entities +Entities Yes @@ -721,7 +721,7 @@ Identical to [the Twitter Media Object](https://developer.twitter.com/en/docs/tw sizes -Sizes +Sizes No @@ -1036,13 +1036,13 @@ Mutually exclusive with link. friendica_activities -Activities +Activities friendica_comments -List of Items +List of Items @@ -1260,13 +1260,13 @@ Mutually exclusive with link. sender -Contact +Contact recipient -Contact +Contact @@ -1471,25 +1471,25 @@ Mutually exclusive with link. medium -Size +Size No large -Size +Size Yes thumb -Size +Size Yes small -Size +Size Yes diff --git a/doc/API-Friendica.md b/doc/en/spec/api/friendica.md similarity index 94% rename from doc/API-Friendica.md rename to doc/en/spec/api/friendica.md index 785cbe41a0..0b9d9d25a8 100644 --- a/doc/API-Friendica.md +++ b/doc/en/spec/api/friendica.md @@ -1,23 +1,22 @@ # Friendica API -* [Home](help) - * [Using the APIs](help/api) +* [Using the APIs](help/spec/api/index) ## Overview Friendica provides the following specific endpoints. -Authentication is the same as described in [Using the APIs](help/api#Authentication). +Authentication is the same as described in [Using the APIs](help/spec/api/index#authentication). ## Entities -These endpoints uses the [Friendica API entities](help/API-Entities). +These endpoints uses the [Friendica API entities](help/spec/api/entities). ## Endpoints ### GET api/friendica/events -Returns a list of [Event](help/API-Entities#Event) entities for the current logged in user. +Returns a list of [Event](help/spec/api/entities#event) entities for the current logged in user. #### Parameters @@ -52,7 +51,7 @@ Delete event from calendar (not the message) ### GET api/externalprofile/show -Returns a [Contact](help/API-Entities#Contact) entity for the provided profile URL. +Returns a [Contact](help/spec/api/entities#contact) entity for the provided profile URL. #### Parameters @@ -60,7 +59,7 @@ Returns a [Contact](help/API-Entities#Contact) entity for the provided profile U ### GET api/statuses/public_timeline -Returns a list of public [Items](help/API-Entities#Item) posted on this node. +Returns a list of public [Items](help/spec/api/entities#item) posted on this node. Equivalent of the local community page. #### Parameters @@ -79,7 +78,7 @@ Equivalent of the local community page. ### GET api/statuses/networkpublic_timeline -Returns a list of public [Items](help/API-Entities#Item) this node is aware of. +Returns a list of public [Items](help/spec/api/entities#item) this node is aware of. Equivalent of the global community page. #### Parameters @@ -206,7 +205,7 @@ Deprecated Twitter received direct message list endpoint. ### GET api/direct_messages/all -Returns all [Private Messages](help/API-Entities#Private+message). +Returns all [Private Messages](help/spec/api/entities#private+message). #### Parameters @@ -219,7 +218,7 @@ Returns all [Private Messages](help/API-Entities#Private+message). ### GET api/direct_messages/conversation -Returns all replies of a single private message conversation. Returns [Private Messages](help/API-Entities#Private+message) +Returns all replies of a single private message conversation. Returns [Private Messages](help/spec/api/entities#private+message) #### Parameters @@ -233,7 +232,7 @@ Returns all replies of a single private message conversation. Returns [Private M ### GET api/direct_messages/sent -Deprecated Twitter sent direct message list endpoint. Returns [Private Messages](help/API-Entities#Private+message). +Deprecated Twitter sent direct message list endpoint. Returns [Private Messages](help/spec/api/entities#private+message). #### Parameters @@ -300,7 +299,7 @@ On error: ### GET api/friendica/direct_messages_search (GET; AUTH) -Returns [Private Messages](help/API-Entities#Private+message) matching the provided search string. +Returns [Private Messages](help/spec/api/entities#private+message) matching the provided search string. #### Parameters @@ -339,7 +338,7 @@ Array of: * `name`: name of the circle * `gid`: id of the circle -* `user`: array of [Contacts](help/API-Entities#Contact) +* `user`: array of [Contacts](help/spec/api/entities#contact) ### POST api/friendica/circle_create @@ -357,7 +356,7 @@ JSON data as Array like the result of [GET api/friendica/circle_show](#GET+api%2 * `gid` * `name` -* List of [Contacts](help/API-Entities#Contact) +* List of [Contacts](help/spec/api/entities#contact) #### Return values @@ -386,7 +385,7 @@ JSON data as array like the result of [GET api/friendica/circle_show](#GET+api%2 * `gid` * `name` -* List of [Contacts](help/API-Entities#Contact) +* List of [Contacts](help/spec/api/entities#contact) #### Return values @@ -423,7 +422,7 @@ Array of: ### GET api/friendica/notifications -Return last 50 [Notifications](help/API-Entities#Notification) for the current user, ordered by date with unseen item on top. +Return last 50 [Notifications](help/spec/api/entities#notification) for the current user, ordered by date with unseen item on top. #### Parameters @@ -439,7 +438,7 @@ Set notification as seen. #### Return values -If the note is linked to an item, returns an [Item](help/API-Entities#Item). +If the note is linked to an item, returns an [Item](help/spec/api/entities#item). Otherwise, a success status is returned: @@ -449,7 +448,7 @@ Otherwise, a success status is returned: ### GET api/friendica/photo -Returns a [Photo](help/API-Entities#Photo). +Returns a [Photo](help/spec/api/entities#photo). #### Parameters @@ -523,7 +522,7 @@ xml: ### GET api/friendica/photos/list -Returns the API user's [Photo List Items](help/API-Entities#Photo+List+Item). +Returns the API user's [Photo List Items](help/spec/api/entities#photo+list+item). #### Return values @@ -772,7 +771,7 @@ On success: ### GET api/friendica/profile/show -Returns the [Profile](help/API-Entities#Profile) data of the authenticated user. +Returns the [Profile](help/spec/api/entities#profile) data of the authenticated user. #### Return values diff --git a/doc/API-GNU-Social.md b/doc/en/spec/api/gnu-social.md similarity index 93% rename from doc/API-GNU-Social.md rename to doc/en/spec/api/gnu-social.md index a33825fc80..8ca1dc9620 100644 --- a/doc/API-GNU-Social.md +++ b/doc/en/spec/api/gnu-social.md @@ -1,17 +1,16 @@ # GNU Social API -* [Home](help) - * [Using the APIs](help/api) +* [Using the APIs](help/spec/api/index) ## Overview Friendica provides the following endpoints defined in [the official GNU Social Twitter-like API reference](https://gnusocial.net/doc/twitterapi). -Authentication is the same as described in [Using the APIs](help/api#Authentication). +Authentication is the same as described in [Using the APIs](help/spec/api/index#authentication). ## Entities -These endpoints use the [Friendica API entities](help/API-Entities). +These endpoints use the [Friendica API entities](help/spec/api/entities). ## Implemented endpoints diff --git a/doc/api.md b/doc/en/spec/api/index.md similarity index 92% rename from doc/api.md rename to doc/en/spec/api/index.md index a3ca4d244d..5fe3cbe712 100644 --- a/doc/api.md +++ b/doc/en/spec/api/index.md @@ -6,10 +6,10 @@ Friendica offers multiple API endpoints to interface with third-party applications: -- [Twitter](help/API-Twitter) -- [Mastodon](help/API-Mastodon) -- [Friendica-specific](help/API-Friendica) -- [GNU Social](help/API-GNU-Social) +- [Twitter](help/spec/api/twitter) +- [Mastodon](help/spec/api/mastodon) +- [Friendica-specific](help/spec/api/friendica) +- [GNU Social](help/spec/api/gnu-social) ## Usage diff --git a/doc/API-Mastodon.md b/doc/en/spec/api/mastodon.md similarity index 99% rename from doc/API-Mastodon.md rename to doc/en/spec/api/mastodon.md index 2cf661611b..d36a78c932 100644 --- a/doc/API-Mastodon.md +++ b/doc/en/spec/api/mastodon.md @@ -1,17 +1,16 @@ # Mastodon API -* [Home](help) - * [Using the APIs](help/api) +* [Using the APIs](help/spec/api/index) ## Overview Friendica provides the following endpoints defined in [the official Mastodon API reference](https://docs.joinmastodon.org/api/). -Authentication is the same as described in [Using the APIs](help/api#Authentication). +Authentication is the same as described in [Using the APIs](help/spec/api/index#authentication). ## Clients -Please find a list of supported apps at [FAQ](help/FAQ#clients). +Please find a list of supported apps at [FAQ](help/user/faq#clients). ## Entities diff --git a/doc/API-Twitter.md b/doc/en/spec/api/twitter.md similarity index 99% rename from doc/API-Twitter.md rename to doc/en/spec/api/twitter.md index fab26ae5b5..10e3ec9073 100644 --- a/doc/API-Twitter.md +++ b/doc/en/spec/api/twitter.md @@ -1,17 +1,16 @@ # Twitter API -* [Home](help) - * [Using the APIs](help/api) +* [Using the APIs](help/spec/api/index) ## Overview Friendica provides the following endpoints defined in the [official Twitter API reference](https://developer.twitter.com/en/docs/api-reference-index). -Authentication is the same as described in [Using the APIs](help/api#Authentication). +Authentication is the same as described in [Using the APIs](help/spec/api/index#authentication). ## Entities -These endpoints use the [Friendica API entities](help/API-Entities). +These endpoints use the [Friendica API entities](help/spec/api/entities). ## Different behaviour @@ -27,7 +26,7 @@ These endpoints use the [Friendica API entities](help/API-Entities). * `cursor` * `trim_user` -* `contributor_details` +* `contributor_details` * `place_id` * `display_coordinates` * `include_rts`: To-Do @@ -57,7 +56,7 @@ These endpoints use the [Friendica API entities](help/API-Entities). - `skip_status` - [POST api/account/update_profile_image](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image) - Additional parameter: - - `profile_id` (optional): Numerical id of the profile for which the image should be used, default is changing the default profile. + - `profile_id` (optional): Numerical id of the profile for which the image should be used, default is changing the default profile. - [POST api/statuses/update](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update) @@ -163,7 +162,7 @@ These endpoints use the [Friendica API entities](help/API-Entities). - Unsupported parameter: - `skip_status`: No status is returned even if it isn't set to true. - Caveats: - - `cursor` trumps `since_id` trumps `max_id` if any combination is provided. + - `cursor` trumps `since_id` trumps `max_id` if any combination is provided. - `user_id` must be the ID of a contact associated with a local user account. - `screen_name` must be associated with a local user account. - `screen_name` trumps `user_id` if both are provided (undocumented Twitter behavior). @@ -243,8 +242,8 @@ These endpoints use the [Friendica API entities](help/API-Entities). - [POST statuses/filter](https://developer.twitter.com/en/docs/tweets/filter-realtime/api-reference/post-statuses-filter) - - + + - [GET statuses/mentions_timeline](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-mentions_timeline) @@ -258,10 +257,10 @@ These endpoints use the [Friendica API entities](help/API-Entities). - [GET statuses/sample](https://developer.twitter.com/en/docs/tweets/sample-realtime/api-reference/get-statuses-sample) - + - [GET compliance/firehose](https://developer.twitter.com/en/docs/tweets/compliance/api-reference/compliance-firehose) - + - [DELETE custom_profiles/destroy.json](https://developer.twitter.com/en/docs/direct-messages/custom-profiles/api-reference/delete-profile) - [GET custom_profiles/:id](https://developer.twitter.com/en/docs/direct-messages/custom-profiles/api-reference/get-profile) @@ -275,8 +274,8 @@ These endpoints use the [Friendica API entities](help/API-Entities). - [POST direct_messages/events/new (message_create)](https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/new-event) - [POST direct_messages/indicate_typing](https://developer.twitter.com/en/docs/direct-messages/typing-indicator-and-read-receipts/api-reference/new-typing-indicator) - [POST direct_messages/mark_read](https://developer.twitter.com/en/docs/direct-messages/typing-indicator-and-read-receipts/api-reference/new-read-receipt) - - + + - [DELETE direct_messages/welcome_messages/destroy](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/delete-welcome-message) - [DELETE direct_messages/welcome_messages/rules/destroy](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/delete-welcome-message-rule) - [PUT direct_messages/welcome_messages/update](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/update-welcome-message) @@ -299,8 +298,8 @@ These endpoints use the [Friendica API entities](help/API-Entities). - [GET trends/available](https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-available) - [GET trends/closest](https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-closest) - [GET trends/place](https://developer.twitter.com/en/docs/trends/trends-for-location/api-reference/get-trends-place) - - + + - [GET geo/id/:place_id](https://developer.twitter.com/en/docs/geo/place-information/api-reference/get-geo-id-place_id) - [GET geo/reverse_geocode](https://developer.twitter.com/en/docs/geo/places-near-location/api-reference/get-geo-reverse_geocode) - [GET geo/search](https://developer.twitter.com/en/docs/geo/places-near-location/api-reference/get-geo-search) diff --git a/doc/database/db_2fa_app_specific_password.md b/doc/en/spec/database/db-2fa_app_specific_password.md similarity index 86% rename from doc/database/db_2fa_app_specific_password.md rename to doc/en/spec/database/db-2fa_app_specific_password.md index 66dd77c95c..dcf8e036fc 100644 --- a/doc/database/db_2fa_app_specific_password.md +++ b/doc/en/spec/database/db-2fa_app_specific_password.md @@ -1,10 +1,8 @@ -Table 2fa_app_specific_password -=========== +# Table 2fa_app_specific_password Two-factor app-specific _password -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------- | ---------------------------------------- | ------------------ | ---- | --- | ------- | -------------- | @@ -15,19 +13,17 @@ Fields | generated | Datetime the password was generated | datetime | NO | | NULL | | | last_used | Datetime the password was last used | datetime | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | --------------- | --------------------- | | PRIMARY | id | | uid_description | uid, description(190) | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_2fa_recovery_codes.md b/doc/en/spec/database/db-2fa_recovery_codes.md similarity index 80% rename from doc/database/db_2fa_recovery_codes.md rename to doc/en/spec/database/db-2fa_recovery_codes.md index 69c34e6547..afb6c72eae 100644 --- a/doc/database/db_2fa_recovery_codes.md +++ b/doc/en/spec/database/db-2fa_recovery_codes.md @@ -1,10 +1,8 @@ -Table 2fa_recovery_codes -=========== +# Table 2fa_recovery_codes Two-factor authentication recovery codes -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------- | ------------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -13,18 +11,16 @@ Fields | generated | Datetime the code was generated | datetime | NO | | NULL | | | used | Datetime the code was used | datetime | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | --------- | | PRIMARY | uid, code | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_2fa_trusted_browser.md b/doc/en/spec/database/db-2fa_trusted_browser.md similarity index 85% rename from doc/database/db_2fa_trusted_browser.md rename to doc/en/spec/database/db-2fa_trusted_browser.md index 18126b49fc..3da75ac020 100644 --- a/doc/database/db_2fa_trusted_browser.md +++ b/doc/en/spec/database/db-2fa_trusted_browser.md @@ -1,10 +1,8 @@ -Table 2fa_trusted_browser -=========== +# Table 2fa_trusted_browser Two-factor authentication trusted browsers -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----------- | ---------------------------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -15,19 +13,17 @@ Fields | created | Datetime the trusted browser was recorded | datetime | NO | | NULL | | | last_used | Datetime the trusted browser was last used | datetime | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ----------- | | PRIMARY | cookie_hash | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_account-suggestion.md b/doc/en/spec/database/db-account-suggestion.md similarity index 79% rename from doc/database/db_account-suggestion.md rename to doc/en/spec/database/db-account-suggestion.md index c86ae2f218..97701ce5c9 100644 --- a/doc/database/db_account-suggestion.md +++ b/doc/en/spec/database/db-account-suggestion.md @@ -1,10 +1,8 @@ -Table account-suggestion -=========== +# Table account-suggestion Account suggestion -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------ | ------------------------------------------------------------ | ------------------ | ---- | --- | ------- | ----- | @@ -13,20 +11,18 @@ Fields | level | level of closeness | smallint unsigned | YES | | NULL | | | ignore | If set, this account will not be suggested again | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | ----------- | | PRIMARY | uid, uri-id | | uri-id_uid | uri-id, uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| uid | [user](help/database/db_user) | uid | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_account-user.md b/doc/en/spec/database/db-account-user.md similarity index 79% rename from doc/database/db_account-user.md rename to doc/en/spec/database/db-account-user.md index 1c3c40172c..d76a257293 100644 --- a/doc/database/db_account-user.md +++ b/doc/en/spec/database/db-account-user.md @@ -1,10 +1,8 @@ -Table account-user -=========== +# Table account-user Remote and local accounts -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------ | ------------------------------------------------------------ | ------------------ | ---- | --- | ------- | -------------- | @@ -12,8 +10,7 @@ Fields | uri-id | Id of the item-uri table entry that contains the account url | int unsigned | NO | | NULL | | | uid | User ID | mediumint unsigned | NO | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | ------------------- | @@ -21,12 +18,11 @@ Indexes | uri-id_uid | UNIQUE, uri-id, uid | | uid_uri-id | uid, uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| uid | [user](help/database/db_user) | uid | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_apcontact.md b/doc/en/spec/database/db-apcontact.md similarity index 95% rename from doc/database/db_apcontact.md rename to doc/en/spec/database/db-apcontact.md index 902d41ae6b..de5584dfd8 100644 --- a/doc/database/db_apcontact.md +++ b/doc/en/spec/database/db-apcontact.md @@ -1,10 +1,8 @@ -Table apcontact -=========== +# Table apcontact ActivityPub compatible contacts - used in the ActivityPub implementation -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------------ | ------------------------------------------------------------------- | -------------- | ---- | --- | ------------------- | ----- | @@ -42,8 +40,7 @@ Fields | statuses_count | Number of posts | int unsigned | YES | | 0 | | | updated | | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ----------- | ---------------- | @@ -56,12 +53,11 @@ Indexes | gsid | gsid | | uri-id | UNIQUE, uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| gsid | [gserver](help/database/db_gserver) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| gsid | [gserver](help/spec/database/db-gserver) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_application-marker.md b/doc/en/spec/database/db-application-marker.md similarity index 80% rename from doc/database/db_application-marker.md rename to doc/en/spec/database/db-application-marker.md index 313ddd05ba..60bb233ebe 100644 --- a/doc/database/db_application-marker.md +++ b/doc/en/spec/database/db-application-marker.md @@ -1,10 +1,8 @@ -Table application-marker -=========== +# Table application-marker Timeline marker -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------------- | ---------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -15,20 +13,18 @@ Fields | version | Version number | smallint unsigned | YES | | NULL | | | updated_at | creation time | datetime | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ----------------------------- | | PRIMARY | application-id, uid, timeline | | uid_id | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| application-id | [application](help/database/db_application) | id | -| uid | [user](help/database/db_user) | uid | +| application-id | [application](help/spec/database/db-application) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_application-token.md b/doc/en/spec/database/db-application-token.md similarity index 83% rename from doc/database/db_application-token.md rename to doc/en/spec/database/db-application-token.md index 9899a5e8b3..b50287be42 100644 --- a/doc/database/db_application-token.md +++ b/doc/en/spec/database/db-application-token.md @@ -1,10 +1,8 @@ -Table application-token -=========== +# Table application-token OAuth user token -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------------- | ------------- | ------------------ | ---- | --- | ------- | ----- | @@ -19,20 +17,18 @@ Fields | follow | Follow scope | boolean | YES | | NULL | | | push | Push scope | boolean | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------------------- | | PRIMARY | application-id, uid | | uid_id | uid, application-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| application-id | [application](help/database/db_application) | id | -| uid | [user](help/database/db_user) | uid | +| application-id | [application](help/spec/database/db-application) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_application.md b/doc/en/spec/database/db-application.md similarity index 92% rename from doc/database/db_application.md rename to doc/en/spec/database/db-application.md index d5d59b5ba6..2b13367e38 100644 --- a/doc/database/db_application.md +++ b/doc/en/spec/database/db-application.md @@ -1,10 +1,8 @@ -Table application -=========== +# Table application OAuth application -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | --------------- | -------------- | ---- | --- | ------- | -------------- | @@ -20,8 +18,7 @@ Fields | follow | Follow scope | boolean | YES | | NULL | | | push | Push scope | boolean | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | --------- | ----------------- | @@ -29,4 +26,4 @@ Indexes | client_id | UNIQUE, client_id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_arrived-activity.md b/doc/en/spec/database/db-arrived-activity.md similarity index 80% rename from doc/database/db_arrived-activity.md rename to doc/en/spec/database/db-arrived-activity.md index d657a3eed6..917724fe39 100644 --- a/doc/database/db_arrived-activity.md +++ b/doc/en/spec/database/db-arrived-activity.md @@ -1,22 +1,19 @@ -Table arrived-activity -=========== +# Table arrived-activity Id of arrived activities -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------- | ---------------------------------- | -------------- | ---- | --- | ------- | ----- | | object-id | object id of the incoming activity | varbinary(383) | NO | PRI | NULL | | | received | Receiving date | datetime | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | --------- | | PRIMARY | object-id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_attach.md b/doc/en/spec/database/db-attach.md similarity index 93% rename from doc/database/db_attach.md rename to doc/en/spec/database/db-attach.md index 38ce83a7c5..0694a157cb 100644 --- a/doc/database/db_attach.md +++ b/doc/en/spec/database/db-attach.md @@ -1,10 +1,8 @@ -Table attach -=========== +# Table attach file attachments -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | ----------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -24,19 +22,17 @@ Fields | backend-class | Storage backend class | tinytext | YES | | NULL | | | backend-ref | Storage backend data reference | text | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | id | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_cache.md b/doc/en/spec/database/db-cache.md similarity index 87% rename from doc/database/db_cache.md rename to doc/en/spec/database/db-cache.md index 27a11daa66..08ac9f2c57 100644 --- a/doc/database/db_cache.md +++ b/doc/en/spec/database/db-cache.md @@ -1,10 +1,8 @@ -Table cache -=========== +# Table cache Stores temporary data -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ---------------------------- | -------------- | ---- | --- | ------------------- | ----- | @@ -13,8 +11,7 @@ Fields | expires | datetime of cache expiration | datetime | NO | | 0001-01-01 00:00:00 | | | updated | datetime of cache insertion | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | --------- | ---------- | @@ -22,4 +19,4 @@ Indexes | k_expires | k, expires | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_channel.md b/doc/en/spec/database/db-channel.md similarity index 94% rename from doc/database/db_channel.md rename to doc/en/spec/database/db-channel.md index 4a469b4ee3..1ad2220cb9 100644 --- a/doc/database/db_channel.md +++ b/doc/en/spec/database/db-channel.md @@ -1,10 +1,8 @@ -Table channel -=========== +# Table channel User defined Channels -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ---------------- | ------------------------------------------------------------------------------------------------- | ------------------ | ---- | --- | ------- | -------------- | @@ -24,19 +22,17 @@ Fields | publish | publish channel content | boolean | YES | | NULL | | | valid | Set, when the full-text-search is valid | boolean | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | id | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_check-full-text-search.md b/doc/en/spec/database/db-check-full-text-search.md similarity index 84% rename from doc/database/db_check-full-text-search.md rename to doc/en/spec/database/db-check-full-text-search.md index dc21d14924..3097fbb0f8 100644 --- a/doc/database/db_check-full-text-search.md +++ b/doc/en/spec/database/db-check-full-text-search.md @@ -1,18 +1,15 @@ -Table check-full-text-search -=========== +# Table check-full-text-search Check for a full text search match in user defined channels before storing the message in the system -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ---------- | ---------------------------------------- | ------------ | ---- | --- | ------- | ----- | | pid | The ID of the process | int unsigned | NO | PRI | NULL | | | searchtext | Simplified text for the full text search | mediumtext | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | -------------------- | @@ -20,4 +17,4 @@ Indexes | searchtext | FULLTEXT, searchtext | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_config.md b/doc/en/spec/database/db-config.md similarity index 86% rename from doc/database/db_config.md rename to doc/en/spec/database/db-config.md index 66796caeb1..d55c24fc4b 100644 --- a/doc/database/db_config.md +++ b/doc/en/spec/database/db-config.md @@ -1,10 +1,8 @@ -Table config -=========== +# Table config main configuration storage -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ------------------------- | ------------- | ---- | --- | ------- | -------------- | @@ -13,8 +11,7 @@ Fields | k | The key of the entry | varbinary(50) | NO | | | | | v | | mediumtext | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | -------------- | @@ -22,4 +19,4 @@ Indexes | cat_k | UNIQUE, cat, k | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_contact-relation.md b/doc/en/spec/database/db-contact-relation.md similarity index 89% rename from doc/database/db_contact-relation.md rename to doc/en/spec/database/db-contact-relation.md index c83c9b8326..883c211789 100644 --- a/doc/database/db_contact-relation.md +++ b/doc/en/spec/database/db-contact-relation.md @@ -1,10 +1,8 @@ -Table contact-relation -=========== +# Table contact-relation Contact relations -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------------- | ----------------------------------------------------------------------- | ----------------- | ---- | --- | ------------------- | ----- | @@ -19,20 +17,18 @@ Fields | relation-thread-score | score for interactions of relation-cid on threads of cid | smallint unsigned | YES | | NULL | | | post-score | score for the amount of posts from cid that can be seen by relation-cid | smallint unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------------ | ----------------- | | PRIMARY | cid, relation-cid | | relation-cid | relation-cid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| cid | [contact](help/database/db_contact) | id | -| relation-cid | [contact](help/database/db_contact) | id | +| cid | [contact](help/spec/database/db-contact) | id | +| relation-cid | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_contact.md b/doc/en/spec/database/db-contact.md similarity index 98% rename from doc/database/db_contact.md rename to doc/en/spec/database/db-contact.md index cd66ce12de..c89eb41e41 100644 --- a/doc/database/db_contact.md +++ b/doc/en/spec/database/db-contact.md @@ -1,10 +1,8 @@ -Table contact -=========== +# Table contact contact table -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -94,8 +92,7 @@ Fields | closeness | Deprecated | tinyint unsigned | NO | | 99 | | | profile-id | Deprecated | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | --------------------------- | ------------------------------------ | @@ -124,13 +121,12 @@ Indexes | gsid_uid_failed | gsid, uid, failed | | uri-id | uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| uri-id | [item-uri](help/database/db_item-uri) | id | -| gsid | [gserver](help/database/db_gserver) | id | +| uid | [user](help/spec/database/db-user) | uid | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| gsid | [gserver](help/spec/database/db-gserver) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_conv.md b/doc/en/spec/database/db-conv.md similarity index 89% rename from doc/database/db_conv.md rename to doc/en/spec/database/db-conv.md index 69815fae7d..f6fafcd4b5 100644 --- a/doc/database/db_conv.md +++ b/doc/en/spec/database/db-conv.md @@ -1,10 +1,8 @@ -Table conv -=========== +# Table conv private messages -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ----------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -17,19 +15,17 @@ Fields | updated | edited timestamp | datetime | NO | | 0001-01-01 00:00:00 | | | subject | subject of initial message | text | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | id | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_delayed-post.md b/doc/en/spec/database/db-delayed-post.md similarity index 82% rename from doc/database/db_delayed-post.md rename to doc/en/spec/database/db-delayed-post.md index 8ab3ff08e4..d00e0a5d62 100644 --- a/doc/database/db_delayed-post.md +++ b/doc/en/spec/database/db-delayed-post.md @@ -1,10 +1,8 @@ -Table delayed-post -=========== +# Table delayed-post Posts that are about to be distributed at a later time -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ---------------------------------------------- | ------------------ | ---- | --- | ------- | -------------- | @@ -14,8 +12,7 @@ Fields | delayed | delay time | datetime | YES | | NULL | | | wid | Workerqueue id | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | --------------------- | @@ -23,12 +20,11 @@ Indexes | uid_uri | UNIQUE, uid, uri(190) | | wid | wid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| wid | [workerqueue](help/database/db_workerqueue) | id | +| uid | [user](help/spec/database/db-user) | uid | +| wid | [workerqueue](help/spec/database/db-workerqueue) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_delivery-queue.md b/doc/en/spec/database/db-delivery-queue.md similarity index 78% rename from doc/database/db_delivery-queue.md rename to doc/en/spec/database/db-delivery-queue.md index 46623a54e0..6f41cd22e4 100644 --- a/doc/database/db_delivery-queue.md +++ b/doc/en/spec/database/db-delivery-queue.md @@ -1,10 +1,8 @@ -Table delivery-queue -=========== +# Table delivery-queue Delivery data for posts for the batch processing -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | --------------------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -16,8 +14,7 @@ Fields | uid | Delivering user | mediumint unsigned | YES | | NULL | | | failed | Number of times the delivery has failed | tinyint | YES | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------------ | ------------- | @@ -26,14 +23,13 @@ Indexes | uid | uid | | cid | cid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| gsid | [gserver](help/database/db_gserver) | id | -| uri-id | [item-uri](help/database/db_item-uri) | id | -| cid | [contact](help/database/db_contact) | id | -| uid | [user](help/database/db_user) | uid | +| gsid | [gserver](help/spec/database/db-gserver) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| cid | [contact](help/spec/database/db-contact) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_diaspora-contact.md b/doc/en/spec/database/db-diaspora-contact.md similarity index 93% rename from doc/database/db_diaspora-contact.md rename to doc/en/spec/database/db-diaspora-contact.md index 5bbc9ab221..db42527dd1 100644 --- a/doc/database/db_diaspora-contact.md +++ b/doc/en/spec/database/db-diaspora-contact.md @@ -1,10 +1,8 @@ -Table diaspora-contact -=========== +# Table diaspora-contact Diaspora compatible contacts - used in the Diaspora implementation -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----------------- | ------------------------------------------------------------ | ------------ | ---- | --- | ------------------- | ----- | @@ -31,8 +29,7 @@ Fields | interacted_count | Number of contacts that interacted with this contact | int unsigned | YES | | 0 | | | post_count | Number of posts and comments | int unsigned | YES | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------------ | @@ -41,12 +38,11 @@ Indexes | alias | alias | | gsid | gsid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| gsid | [gserver](help/database/db_gserver) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| gsid | [gserver](help/spec/database/db-gserver) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_diaspora-interaction.md b/doc/en/spec/database/db-diaspora-interaction.md similarity index 76% rename from doc/database/db_diaspora-interaction.md rename to doc/en/spec/database/db-diaspora-interaction.md index 4ac4325909..6ec9a83677 100644 --- a/doc/database/db_diaspora-interaction.md +++ b/doc/en/spec/database/db-diaspora-interaction.md @@ -1,28 +1,24 @@ -Table diaspora-interaction -=========== +# Table diaspora-interaction Signed Diaspora Interaction -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----------- | --------------------------------------------------------- | ------------ | ---- | --- | ------- | ----- | | uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | | | interaction | The Diaspora interaction | mediumtext | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_endpoint.md b/doc/en/spec/database/db-endpoint.md similarity index 83% rename from doc/database/db_endpoint.md rename to doc/en/spec/database/db-endpoint.md index 890a9f1bb9..c67150a630 100644 --- a/doc/database/db_endpoint.md +++ b/doc/en/spec/database/db-endpoint.md @@ -1,10 +1,8 @@ -Table endpoint -=========== +# Table endpoint ActivityPub endpoints - used in the ActivityPub implementation -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------ | -------------------------------------------------------------- | -------------- | ---- | --- | ------- | ----- | @@ -12,19 +10,17 @@ Fields | type | | varchar(20) | NO | | NULL | | | owner-uri-id | Id of the item-uri table entry that contains the apcontact url | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ----------------- | -------------------------- | | PRIMARY | url | | owner-uri-id_type | UNIQUE, owner-uri-id, type | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| owner-uri-id | [item-uri](help/database/db_item-uri) | id | +| owner-uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_event.md b/doc/en/spec/database/db-event.md similarity index 92% rename from doc/database/db_event.md rename to doc/en/spec/database/db-event.md index c7daea9873..b9ef8d6e10 100644 --- a/doc/database/db_event.md +++ b/doc/en/spec/database/db-event.md @@ -1,10 +1,8 @@ -Table event -=========== +# Table event Events -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------- | ---------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -29,8 +27,7 @@ Fields | deny_cid | Access Control - list of denied contact.id | mediumtext | YES | | NULL | | | deny_gid | Access Control - list of denied circles | mediumtext | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | --------- | ---------- | @@ -39,13 +36,12 @@ Indexes | cid | cid | | uri-id | uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| cid | [contact](help/database/db_contact) | id | -| uri-id | [item-uri](help/database/db_item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | +| cid | [contact](help/spec/database/db-contact) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_fetch-entry.md b/doc/en/spec/database/db-fetch-entry.md similarity index 82% rename from doc/database/db_fetch-entry.md rename to doc/en/spec/database/db-fetch-entry.md index e7485f212a..9ac4c257d6 100644 --- a/doc/database/db_fetch-entry.md +++ b/doc/en/spec/database/db-fetch-entry.md @@ -1,10 +1,8 @@ -Table fetch-entry -=========== +# Table fetch-entry -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ---------------------------------- | -------------- | ---- | --- | ------------------- | -------------- | @@ -13,8 +11,7 @@ Fields | created | Creation date of the fetch request | datetime | NO | | 0001-01-01 00:00:00 | | | wid | Workerqueue id | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ----------- | @@ -23,11 +20,10 @@ Indexes | created | created | | wid | wid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| wid | [workerqueue](help/database/db_workerqueue) | id | +| wid | [workerqueue](help/spec/database/db-workerqueue) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_fetched-activity.md b/doc/en/spec/database/db-fetched-activity.md similarity index 80% rename from doc/database/db_fetched-activity.md rename to doc/en/spec/database/db-fetched-activity.md index 076d8c2e87..25fc77d4a9 100644 --- a/doc/database/db_fetched-activity.md +++ b/doc/en/spec/database/db-fetched-activity.md @@ -1,22 +1,19 @@ -Table fetched-activity -=========== +# Table fetched-activity Id of fetched activities -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------- | ----------------------------- | -------------- | ---- | --- | ------- | ----- | | object-id | object id of fetched activity | varbinary(383) | NO | PRI | NULL | | | received | Receiving date | datetime | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | --------- | | PRIMARY | object-id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_fsuggest.md b/doc/en/spec/database/db-fsuggest.md similarity index 84% rename from doc/database/db_fsuggest.md rename to doc/en/spec/database/db-fsuggest.md index b602567cee..d7e8c4df1d 100644 --- a/doc/database/db_fsuggest.md +++ b/doc/en/spec/database/db-fsuggest.md @@ -1,10 +1,8 @@ -Table fsuggest -=========== +# Table fsuggest friend suggestion stuff -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ----------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -18,8 +16,7 @@ Fields | note | | text | YES | | NULL | | | created | | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | @@ -27,12 +24,11 @@ Indexes | cid | cid | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| cid | [contact](help/database/db_contact) | id | +| uid | [user](help/spec/database/db-user) | uid | +| cid | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_group.md b/doc/en/spec/database/db-group.md similarity index 86% rename from doc/database/db_group.md rename to doc/en/spec/database/db-group.md index f717247ad3..43e406e9d5 100644 --- a/doc/database/db_group.md +++ b/doc/en/spec/database/db-group.md @@ -1,10 +1,8 @@ -Table group -=========== +# Table group privacy circles, circle info -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ----------------------------------------------------------------------------------------- | ------------------ | ---- | --- | ------- | -------------- | @@ -15,8 +13,7 @@ Fields | cid | Contact id of group. When this field is filled then the members are synced automatically. | int unsigned | YES | | NULL | | | name | human readable name of circle | varchar(255) | NO | | | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | @@ -24,12 +21,11 @@ Indexes | uid | uid | | cid | cid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| cid | [contact](help/database/db_contact) | id | +| uid | [user](help/spec/database/db-user) | uid | +| cid | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_group_member.md b/doc/en/spec/database/db-group_member.md similarity index 80% rename from doc/database/db_group_member.md rename to doc/en/spec/database/db-group_member.md index efe83e4aed..bcc47cbcba 100644 --- a/doc/database/db_group_member.md +++ b/doc/en/spec/database/db-group_member.md @@ -1,10 +1,8 @@ -Table group_member -=========== +# Table group_member privacy circles, member info -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ---------- | ---------------------------------------------------------- | ------------ | ---- | --- | ------- | -------------- | @@ -12,8 +10,7 @@ Fields | gid | group.id of the associated circle | int unsigned | NO | | 0 | | | contact-id | contact.id of the member assigned to the associated circle | int unsigned | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------------- | ----------------------- | @@ -21,12 +18,11 @@ Indexes | contactid | contact-id | | gid_contactid | UNIQUE, gid, contact-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| gid | [group](help/database/db_group) | id | -| contact-id | [contact](help/database/db_contact) | id | +| gid | [group](help/spec/database/db-group) | id | +| contact-id | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_gserver-tag.md b/doc/en/spec/database/db-gserver-tag.md similarity index 76% rename from doc/database/db_gserver-tag.md rename to doc/en/spec/database/db-gserver-tag.md index 82b0ccc881..19879e27c1 100644 --- a/doc/database/db_gserver-tag.md +++ b/doc/en/spec/database/db-gserver-tag.md @@ -1,29 +1,25 @@ -Table gserver-tag -=========== +# Table gserver-tag Tags that the server has subscribed -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ---------- | ---------------------------------- | ------------ | ---- | --- | ------- | ----- | | gserver-id | The id of the gserver | int unsigned | NO | PRI | 0 | | | tag | Tag that the server has subscribed | varchar(100) | NO | PRI | | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | --------------- | | PRIMARY | gserver-id, tag | | tag | tag | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| gserver-id | [gserver](help/database/db_gserver) | id | +| gserver-id | [gserver](help/spec/database/db-gserver) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_gserver.md b/doc/en/spec/database/db-gserver.md similarity index 96% rename from doc/database/db_gserver.md rename to doc/en/spec/database/db-gserver.md index 22939ec2bc..2b33f72c5a 100644 --- a/doc/database/db_gserver.md +++ b/doc/en/spec/database/db-gserver.md @@ -1,10 +1,8 @@ -Table gserver -=========== +# Table gserver Global servers -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------------- | -------------------------------------------------------------- | ---------------- | ---- | --- | ------------------- | -------------- | @@ -43,8 +41,7 @@ Fields | next_contact | Next connection request | datetime | YES | | 0001-01-01 00:00:00 | | | redirect-gsid | Target Gserver id in case of a redirect | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------------- | ----------------- | @@ -54,11 +51,10 @@ Indexes | network | network | | redirect-gsid | redirect-gsid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| redirect-gsid | [gserver](help/database/db_gserver) | id | +| redirect-gsid | [gserver](help/spec/database/db-gserver) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_hook.md b/doc/en/spec/database/db-hook.md similarity index 93% rename from doc/database/db_hook.md rename to doc/en/spec/database/db-hook.md index 0ad0981f0c..0d02a77493 100644 --- a/doc/database/db_hook.md +++ b/doc/en/spec/database/db-hook.md @@ -1,10 +1,8 @@ -Table hook -=========== +# Table hook addon hook registry -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | ---------------------------------------------------------------------------------------------------------- | ----------------- | ---- | --- | ------- | -------------- | @@ -14,8 +12,7 @@ Fields | function | function name of hook handler | varbinary(200) | NO | | | | | priority | not yet implemented - can be used to sort conflicts in hook handling by calling handlers in priority order | smallint unsigned | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------------------ | ---------------------------- | @@ -24,4 +21,4 @@ Indexes | hook_file_function | UNIQUE, hook, file, function | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_inbox-entry-receiver.md b/doc/en/spec/database/db-inbox-entry-receiver.md similarity index 67% rename from doc/database/db_inbox-entry-receiver.md rename to doc/en/spec/database/db-inbox-entry-receiver.md index f905289d27..e4f3de395f 100644 --- a/doc/database/db_inbox-entry-receiver.md +++ b/doc/en/spec/database/db-inbox-entry-receiver.md @@ -1,30 +1,26 @@ -Table inbox-entry-receiver -=========== +# Table inbox-entry-receiver Receiver for the incoming activity -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | ----------- | ------------------ | ---- | --- | ------- | ----- | | queue-id | | int unsigned | NO | PRI | NULL | | | uid | User id | mediumint unsigned | NO | PRI | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------------- | | PRIMARY | queue-id, uid | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| queue-id | [inbox-entry](help/database/db_inbox-entry) | id | -| uid | [user](help/database/db_user) | uid | +| queue-id | [inbox-entry](help/spec/database/db-inbox-entry) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_inbox-entry.md b/doc/en/spec/database/db-inbox-entry.md similarity index 92% rename from doc/database/db_inbox-entry.md rename to doc/en/spec/database/db-inbox-entry.md index e18e66f240..e386762dd2 100644 --- a/doc/database/db_inbox-entry.md +++ b/doc/en/spec/database/db-inbox-entry.md @@ -1,10 +1,8 @@ -Table inbox-entry -=========== +# Table inbox-entry Incoming activity -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------------ | -------------------------------------- | ---------------- | ---- | --- | ------- | -------------- | @@ -25,8 +23,7 @@ Fields | wid | Workerqueue id | int unsigned | YES | | NULL | | | retrial | Retrial counter | tinyint unsigned | YES | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ----------- | ------------------- | @@ -36,11 +33,10 @@ Indexes | received | received | | wid | wid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| wid | [workerqueue](help/database/db_workerqueue) | id | +| wid | [workerqueue](help/spec/database/db-workerqueue) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_inbox-status.md b/doc/en/spec/database/db-inbox-status.md similarity index 85% rename from doc/database/db_inbox-status.md rename to doc/en/spec/database/db-inbox-status.md index ccb28e9bb2..e5c6c7c175 100644 --- a/doc/database/db_inbox-status.md +++ b/doc/en/spec/database/db-inbox-status.md @@ -1,10 +1,8 @@ -Table inbox-status -=========== +# Table inbox-status Status of ActivityPub inboxes -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | ------------------------------------ | -------------- | ---- | --- | ------------------- | ----- | @@ -18,8 +16,7 @@ Fields | archive | Is the inbox archived? | boolean | NO | | 0 | | | shared | Is it a shared inbox? | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | @@ -27,12 +24,11 @@ Indexes | uri-id | uri-id | | gsid | gsid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| gsid | [gserver](help/database/db_gserver) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| gsid | [gserver](help/spec/database/db-gserver) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_intro.md b/doc/en/spec/database/db-intro.md similarity index 85% rename from doc/database/db_intro.md rename to doc/en/spec/database/db-intro.md index da6dc849ea..2d400cb251 100644 --- a/doc/database/db_intro.md +++ b/doc/en/spec/database/db-intro.md @@ -1,10 +1,8 @@ -Table intro -=========== +# Table intro -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----------- | ----------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -21,8 +19,7 @@ Fields | blocked | deprecated | boolean | NO | | 0 | | | ignore | | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ----------- | ----------- | @@ -31,13 +28,12 @@ Indexes | suggest-cid | suggest-cid | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| contact-id | [contact](help/database/db_contact) | id | -| suggest-cid | [contact](help/database/db_contact) | id | +| uid | [user](help/spec/database/db-user) | uid | +| contact-id | [contact](help/spec/database/db-contact) | id | +| suggest-cid | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_item-uri.md b/doc/en/spec/database/db-item-uri.md similarity index 85% rename from doc/database/db_item-uri.md rename to doc/en/spec/database/db-item-uri.md index a6b006ec79..0612de274b 100644 --- a/doc/database/db_item-uri.md +++ b/doc/en/spec/database/db-item-uri.md @@ -1,10 +1,8 @@ -Table item-uri -=========== +# Table item-uri URI and GUID for items -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ------------------------------- | -------------- | ---- | --- | ------- | -------------- | @@ -12,8 +10,7 @@ Fields | uri | URI of an item | varbinary(383) | NO | | NULL | | | guid | A unique identifier for an item | varbinary(255) | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ----------- | @@ -22,4 +19,4 @@ Indexes | guid | guid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_key-value.md b/doc/en/spec/database/db-key-value.md similarity index 83% rename from doc/database/db_key-value.md rename to doc/en/spec/database/db-key-value.md index 2ed3baa48c..a184452ff5 100644 --- a/doc/database/db_key-value.md +++ b/doc/en/spec/database/db-key-value.md @@ -1,10 +1,8 @@ -Table key-value -=========== +# Table key-value A key value storage -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ---------- | ---------------------------- | ------------- | ---- | --- | ------- | ----- | @@ -12,12 +10,11 @@ Fields | v | | mediumtext | YES | | NULL | | | updated_at | timestamp of the last update | int unsigned | NO | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | k | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_locks.md b/doc/en/spec/database/db-locks.md similarity index 89% rename from doc/database/db_locks.md rename to doc/en/spec/database/db-locks.md index dc5371184d..3d07a0f9eb 100644 --- a/doc/database/db_locks.md +++ b/doc/en/spec/database/db-locks.md @@ -1,10 +1,8 @@ -Table locks -=========== +# Table locks -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ---------------------------- | ------------ | ---- | --- | ------------------- | -------------- | @@ -14,8 +12,7 @@ Fields | pid | Process ID | int unsigned | NO | | 0 | | | expires | datetime of cache expiration | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------------ | ------------- | @@ -23,4 +20,4 @@ Indexes | name_expires | name, expires | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_mail.md b/doc/en/spec/database/db-mail.md similarity index 91% rename from doc/database/db_mail.md rename to doc/en/spec/database/db-mail.md index 834b556f6f..05c25b154e 100644 --- a/doc/database/db_mail.md +++ b/doc/en/spec/database/db-mail.md @@ -1,10 +1,8 @@ -Table mail -=========== +# Table mail private messages -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | -------------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -31,8 +29,7 @@ Fields | thr-parent-id | Id of the item-uri table that contains the thread parent uri | int unsigned | YES | | NULL | | | created | creation time of the private message | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------------- | -------------- | @@ -47,15 +44,14 @@ Indexes | parent-uri-id | parent-uri-id | | thr-parent-id | thr-parent-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| author-id | [contact](help/database/db_contact) | id | -| uri-id | [item-uri](help/database/db_item-uri) | id | -| parent-uri-id | [item-uri](help/database/db_item-uri) | id | -| thr-parent-id | [item-uri](help/database/db_item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | +| author-id | [contact](help/spec/database/db-contact) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| parent-uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| thr-parent-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_mailacct.md b/doc/en/spec/database/db-mailacct.md similarity index 90% rename from doc/database/db_mailacct.md rename to doc/en/spec/database/db-mailacct.md index 59f34250ce..dbbc732759 100644 --- a/doc/database/db_mailacct.md +++ b/doc/en/spec/database/db-mailacct.md @@ -1,10 +1,8 @@ -Table mailacct -=========== +# Table mailacct Mail account data for fetching mails -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------ | ------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -22,19 +20,17 @@ Fields | pubmail | | boolean | NO | | 0 | | | last_check | | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | id | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_manage.md b/doc/en/spec/database/db-manage.md similarity index 76% rename from doc/database/db_manage.md rename to doc/en/spec/database/db-manage.md index 8a2228a5ef..1ecc811ee9 100644 --- a/doc/database/db_manage.md +++ b/doc/en/spec/database/db-manage.md @@ -1,10 +1,8 @@ -Table manage -=========== +# Table manage table of accounts that can manage each other -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ------------- | ------------------ | ---- | --- | ------- | -------------- | @@ -12,8 +10,7 @@ Fields | uid | User id | mediumint unsigned | NO | | 0 | | | mid | User id | mediumint unsigned | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ---------------- | @@ -21,12 +18,11 @@ Indexes | uid_mid | UNIQUE, uid, mid | | mid | mid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| mid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | +| mid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_notification.md b/doc/en/spec/database/db-notification.md similarity index 87% rename from doc/database/db_notification.md rename to doc/en/spec/database/db-notification.md index a2f319ead4..a0f4ea2255 100644 --- a/doc/database/db_notification.md +++ b/doc/en/spec/database/db-notification.md @@ -1,10 +1,8 @@ -Table notification -=========== +# Table notification notifications -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | ------------------------------------------------------------------------------ | ------------------ | ---- | --- | ------- | -------------- | @@ -19,8 +17,7 @@ Fields | seen | Seen on the desktop | boolean | YES | | 0 | | | dismissed | Dismissed via the API | boolean | YES | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ----------------------------------- | ----------------------------------------------- | @@ -33,15 +30,14 @@ Indexes | seen_uid | seen, uid | | uid_type_parent-uri-id_actor-id | uid, type, parent-uri-id, actor-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| vid | [verb](help/database/db_verb) | id | -| actor-id | [contact](help/database/db_contact) | id | -| target-uri-id | [item-uri](help/database/db_item-uri) | id | -| parent-uri-id | [item-uri](help/database/db_item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | +| vid | [verb](help/spec/database/db-verb) | id | +| actor-id | [contact](help/spec/database/db-contact) | id | +| target-uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| parent-uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_notify-threads.md b/doc/en/spec/database/db-notify-threads.md similarity index 81% rename from doc/database/db_notify-threads.md rename to doc/en/spec/database/db-notify-threads.md index 82ed225f7d..336338619a 100644 --- a/doc/database/db_notify-threads.md +++ b/doc/en/spec/database/db-notify-threads.md @@ -1,10 +1,8 @@ -Table notify-threads -=========== +# Table notify-threads -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------------------- | --------------------------------------------- | ------------------ | ---- | --- | ------- | -------------- | @@ -15,8 +13,7 @@ Fields | parent-item | | int unsigned | NO | | 0 | | | receiver-uid | User id | mediumint unsigned | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | -------------------- | -------------------- | @@ -25,13 +22,12 @@ Indexes | receiver-uid | receiver-uid | | notify-id | notify-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| notify-id | [notify](help/database/db_notify) | id | -| master-parent-uri-id | [item-uri](help/database/db_item-uri) | id | -| receiver-uid | [user](help/database/db_user) | uid | +| notify-id | [notify](help/spec/database/db-notify) | id | +| master-parent-uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| receiver-uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_notify.md b/doc/en/spec/database/db-notify.md similarity index 91% rename from doc/database/db_notify.md rename to doc/en/spec/database/db-notify.md index bad3fe1d39..1fab5df87a 100644 --- a/doc/database/db_notify.md +++ b/doc/en/spec/database/db-notify.md @@ -1,10 +1,8 @@ -Table notify -=========== +# Table notify [Deprecated] User notifications -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | --------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -27,8 +25,7 @@ Fields | name_cache | Cached bbcode parsing of name | tinytext | YES | | NULL | | | msg_cache | Cached bbcode parsing of msg | mediumtext | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------------- | -------------------- | @@ -39,13 +36,12 @@ Indexes | uri-id | uri-id | | parent-uri-id | parent-uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| uri-id | [item-uri](help/database/db_item-uri) | id | -| parent-uri-id | [item-uri](help/database/db_item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| parent-uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_openwebauth-token.md b/doc/en/spec/database/db-openwebauth-token.md similarity index 85% rename from doc/database/db_openwebauth-token.md rename to doc/en/spec/database/db-openwebauth-token.md index c330623d92..8f2bdd8eb4 100644 --- a/doc/database/db_openwebauth-token.md +++ b/doc/en/spec/database/db-openwebauth-token.md @@ -1,10 +1,8 @@ -Table openwebauth-token -=========== +# Table openwebauth-token Store OpenWebAuth token to verify contacts -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | -------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -15,19 +13,17 @@ Fields | meta | | varchar(255) | NO | | | | | created | datetime of creation | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | id | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_parsed_url.md b/doc/en/spec/database/db-parsed_url.md similarity index 92% rename from doc/database/db_parsed_url.md rename to doc/en/spec/database/db-parsed_url.md index 050c5cb7c9..71ffd3af67 100644 --- a/doc/database/db_parsed_url.md +++ b/doc/en/spec/database/db-parsed_url.md @@ -1,10 +1,8 @@ -Table parsed_url -=========== +# Table parsed_url cache for 'parse_url' queries -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | --------------------------------------------------- | ---------- | ---- | --- | ------------------- | ----- | @@ -16,8 +14,7 @@ Fields | created | datetime of creation | datetime | NO | | 0001-01-01 00:00:00 | | | expires | datetime of expiration | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | -------------------------- | @@ -26,4 +23,4 @@ Indexes | expires | expires | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_pconfig.md b/doc/en/spec/database/db-pconfig.md similarity index 82% rename from doc/database/db_pconfig.md rename to doc/en/spec/database/db-pconfig.md index cf9b0d7810..c516f43210 100644 --- a/doc/database/db_pconfig.md +++ b/doc/en/spec/database/db-pconfig.md @@ -1,10 +1,8 @@ -Table pconfig -=========== +# Table pconfig personal (per user) configuration storage -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ----------- | ------------------ | ---- | --- | ------- | -------------- | @@ -14,19 +12,17 @@ Fields | k | Key | varchar(100) | NO | | | | | v | Value | mediumtext | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | --------- | ------------------- | | PRIMARY | id | | uid_cat_k | UNIQUE, uid, cat, k | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_permissionset.md b/doc/en/spec/database/db-permissionset.md similarity index 89% rename from doc/database/db_permissionset.md rename to doc/en/spec/database/db-permissionset.md index 82059b2f3d..e0e0c14025 100644 --- a/doc/database/db_permissionset.md +++ b/doc/en/spec/database/db-permissionset.md @@ -1,10 +1,8 @@ -Table permissionset -=========== +# Table permissionset -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------- | ------------------------------------------------------ | ------------------ | ---- | --- | ------- | -------------- | @@ -15,19 +13,17 @@ Fields | deny_cid | Access Control - list of denied contact.id | mediumtext | YES | | NULL | | | deny_gid | Access Control - list of denied circles | mediumtext | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ----------------------------------------- | ------------------------------------------------------------- | | PRIMARY | id | | uid_allow_cid_allow_gid_deny_cid_deny_gid | uid, allow_cid(50), allow_gid(30), deny_cid(50), deny_gid(30) | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_photo.md b/doc/en/spec/database/db-photo.md similarity index 96% rename from doc/database/db_photo.md rename to doc/en/spec/database/db-photo.md index c41e913ca3..5fcb882864 100644 --- a/doc/database/db_photo.md +++ b/doc/en/spec/database/db-photo.md @@ -1,10 +1,8 @@ -Table photo -=========== +# Table photo photo storage -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | ------------------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -38,8 +36,7 @@ Fields | backend-ref | Storage backend data reference | text | YES | | NULL | | | updated | | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ----------------------------- | ------------------------------------ | @@ -52,12 +49,11 @@ Indexes | resource-id | resource-id | | uid_photo-type | uid, photo-type | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| contact-id | [contact](help/database/db_contact) | id | +| uid | [user](help/spec/database/db-user) | uid | +| contact-id | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-activity.md b/doc/en/spec/database/db-post-activity.md similarity index 79% rename from doc/database/db_post-activity.md rename to doc/en/spec/database/db-post-activity.md index 56d04d37d7..1d9682ece0 100644 --- a/doc/database/db_post-activity.md +++ b/doc/en/spec/database/db-post-activity.md @@ -1,10 +1,8 @@ -Table post-activity -=========== +# Table post-activity Original remote activity -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | --------------------------------------------------------- | ------------ | ---- | --- | ------- | ----- | @@ -12,18 +10,16 @@ Fields | activity | Original activity | mediumtext | YES | | NULL | | | received | | datetime | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-category.md b/doc/en/spec/database/db-post-category.md similarity index 78% rename from doc/database/db_post-category.md rename to doc/en/spec/database/db-post-category.md index f28e306f17..7c2de11b0e 100644 --- a/doc/database/db_post-category.md +++ b/doc/en/spec/database/db-post-category.md @@ -1,10 +1,8 @@ -Table post-category -=========== +# Table post-category post relation to categories -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------ | --------------------------------------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -13,8 +11,7 @@ Fields | type | | tinyint unsigned | NO | PRI | 0 | | | tid | | int unsigned | NO | PRI | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | ---------------------- | @@ -22,13 +19,12 @@ Indexes | tid | tid | | uid_uri-id | uid, uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| uid | [user](help/database/db_user) | uid | -| tid | [tag](help/database/db_tag) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | +| tid | [tag](help/spec/database/db-tag) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-collection.md b/doc/en/spec/database/db-post-collection.md similarity index 77% rename from doc/database/db_post-collection.md rename to doc/en/spec/database/db-post-collection.md index a0197e66bc..e8950fb686 100644 --- a/doc/database/db_post-collection.md +++ b/doc/en/spec/database/db-post-collection.md @@ -1,10 +1,8 @@ -Table post-collection -=========== +# Table post-collection Collection of posts -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------- | --------------------------------------------------------- | ---------------- | ---- | --- | ------- | ----- | @@ -12,8 +10,7 @@ Fields | type | 0 - Featured | tinyint unsigned | NO | PRI | 0 | | | author-id | Author of the featured post | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | --------- | ------------ | @@ -21,12 +18,11 @@ Indexes | type | type | | author-id | author-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| author-id | [contact](help/database/db_contact) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| author-id | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-content.md b/doc/en/spec/database/db-post-content.md similarity index 92% rename from doc/database/db_post-content.md rename to doc/en/spec/database/db-post-content.md index d1ae90f278..5dd4a6bae1 100644 --- a/doc/database/db_post-content.md +++ b/doc/en/spec/database/db-post-content.md @@ -1,16 +1,14 @@ -Table post-content -=========== +# Table post-content Content for all posts -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------- | ---- | --- | ------- | ----- | | uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | | | title | item title | varchar(255) | NO | | | | -| content-warning | | varchar(255) | NO | | | | +| content-warning | | varchar(500) | NO | | | | | body | item body content | mediumtext | YES | | NULL | | | raw-body | Body without embedded media links | mediumtext | YES | | NULL | | | quote-uri-id | Id of the item-uri table that contains the quoted uri | int unsigned | YES | | NULL | | @@ -28,8 +26,7 @@ Fields | resource-id | Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type | varchar(32) | NO | | | | | plink | permalink or URL to a displayable copy of the message at its source | varbinary(383) | NO | | | | -Indexes ------------- +## Indexes | Name | Fields | | ------------ | ------------ | @@ -38,12 +35,11 @@ Indexes | resource-id | resource-id | | quote-uri-id | quote-uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| quote-uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| quote-uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-counts.md b/doc/en/spec/database/db-post-counts.md similarity index 80% rename from doc/database/db_post-counts.md rename to doc/en/spec/database/db-post-counts.md index db2a8fd36d..eb128552b4 100644 --- a/doc/database/db_post-counts.md +++ b/doc/en/spec/database/db-post-counts.md @@ -1,10 +1,8 @@ -Table post-counts -=========== +# Table post-counts Original remote activity -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | ----------------------------------------------------------- | ----------------- | ---- | --- | ------- | ----- | @@ -14,8 +12,7 @@ Fields | parent-uri-id | Id of the item-uri table that contains the parent uri | int unsigned | YES | | NULL | | | count | Number of activities | int unsigned | YES | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------------- | --------------------- | @@ -23,13 +20,12 @@ Indexes | vid | vid | | parent-uri-id | parent-uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| vid | [verb](help/database/db_verb) | id | -| parent-uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| vid | [verb](help/spec/database/db-verb) | id | +| parent-uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-delivery-data.md b/doc/en/spec/database/db-post-delivery-data.md similarity index 93% rename from doc/database/db_post-delivery-data.md rename to doc/en/spec/database/db-post-delivery-data.md index 332cfbcb3b..e938b58e62 100644 --- a/doc/database/db_post-delivery-data.md +++ b/doc/en/spec/database/db-post-delivery-data.md @@ -1,10 +1,8 @@ -Table post-delivery-data -=========== +# Table post-delivery-data Delivery data for items -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ---- | --- | ------- | ----- | @@ -19,18 +17,16 @@ Fields | legacy_dfrn | Number of successful deliveries via legacy DFRN | mediumint | NO | | 0 | | | diaspora | Number of successful deliveries via Diaspora | mediumint | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-delivery.md b/doc/en/spec/database/db-post-delivery.md similarity index 83% rename from doc/database/db_post-delivery.md rename to doc/en/spec/database/db-post-delivery.md index 2a766eea56..d234df026a 100644 --- a/doc/database/db_post-delivery.md +++ b/doc/en/spec/database/db-post-delivery.md @@ -1,10 +1,8 @@ -Table post-delivery -=========== +# Table post-delivery Delivery data for posts for the batch processing -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------- | --------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | ----- | @@ -16,8 +14,7 @@ Fields | failed | Number of times the delivery has failed | tinyint | YES | | 0 | | | receivers | JSON encoded array with the receiving contacts | mediumtext | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ---------------- | ----------------- | @@ -25,13 +22,12 @@ Indexes | inbox-id_created | inbox-id, created | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| inbox-id | [item-uri](help/database/db_item-uri) | id | -| uid | [user](help/database/db_user) | uid | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| inbox-id | [item-uri](help/spec/database/db-item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-engagement.md b/doc/en/spec/database/db-post-engagement.md similarity index 90% rename from doc/database/db_post-engagement.md rename to doc/en/spec/database/db-post-engagement.md index 31ae5e4e41..e42381ac70 100644 --- a/doc/database/db_post-engagement.md +++ b/doc/en/spec/database/db-post-engagement.md @@ -1,10 +1,8 @@ -Table post-engagement -=========== +# Table post-engagement Engagement data per post -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------ | --------------------------------------------------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -21,8 +19,7 @@ Fields | comments | Number of comments | mediumint unsigned | YES | | NULL | | | activities | Number of activities (like, dislike, ...) | mediumint unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | -------------------- | @@ -31,12 +28,11 @@ Indexes | created | created | | searchtext | FULLTEXT, searchtext | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| owner-id | [contact](help/database/db_contact) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| owner-id | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-history.md b/doc/en/spec/database/db-post-history.md similarity index 82% rename from doc/database/db_post-history.md rename to doc/en/spec/database/db-post-history.md index d3e967411e..0df78a4129 100644 --- a/doc/database/db_post-history.md +++ b/doc/en/spec/database/db-post-history.md @@ -1,22 +1,22 @@ -Table post-history -=========== +# Table post-history Post history -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------- | ---- | --- | ------------------- | ----- | | uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | | | edited | Date of edit | datetime | NO | PRI | 0001-01-01 00:00:00 | | | title | item title | varchar(255) | NO | | | | -| content-warning | | varchar(255) | NO | | | | +| content-warning | | varchar(500) | NO | | | | | body | item body content | mediumtext | YES | | NULL | | | raw-body | Body without embedded media links | mediumtext | YES | | NULL | | +| quote-uri-id | Id of the item-uri table that contains the quoted uri | int unsigned | YES | | NULL | | | location | text location where this item originated | varchar(255) | NO | | | | | coord | longitude/latitude pair representing location where this item originated | varchar(255) | NO | | | | | language | Language information about this post | text | YES | | NULL | | +| sensitive | If true, this post contains sensitive content | boolean | YES | | NULL | | | app | application which generated this item | varchar(255) | NO | | | | | rendered-hash | | varchar(32) | NO | | | | | rendered-html | item.body converted to html | mediumtext | YES | | NULL | | @@ -27,18 +27,18 @@ Fields | resource-id | Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type | varchar(32) | NO | | | | | plink | permalink or URL to a displayable copy of the message at its source | varbinary(383) | NO | | | | -Indexes ------------- +## Indexes -| Name | Fields | -| ------- | -------------- | -| PRIMARY | uri-id, edited | +| Name | Fields | +| ------------ | -------------- | +| PRIMARY | uri-id, edited | +| quote-uri-id | quote-uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| quote-uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-link.md b/doc/en/spec/database/db-post-link.md similarity index 88% rename from doc/database/db_post-link.md rename to doc/en/spec/database/db-post-link.md index cee382f3d7..2a650a372b 100644 --- a/doc/database/db_post-link.md +++ b/doc/en/spec/database/db-post-link.md @@ -1,10 +1,8 @@ -Table post-link -=========== +# Table post-link Post related external links -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | --------------------------------------------------------- | ----------------- | ---- | --- | ------- | -------------- | @@ -16,19 +14,17 @@ Fields | width | Width of the media | smallint unsigned | YES | | NULL | | | blurhash | BlurHash representation of the link | varbinary(255) | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | ------------------- | | PRIMARY | id | | uri-id-url | UNIQUE, uri-id, url | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-media.md b/doc/en/spec/database/db-post-media.md similarity index 90% rename from doc/database/db_post-media.md rename to doc/en/spec/database/db-post-media.md index 85ae290806..4e1551912d 100644 --- a/doc/database/db_post-media.md +++ b/doc/en/spec/database/db-post-media.md @@ -1,10 +1,8 @@ -Table post-media -=========== +# Table post-media Attached media -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------- | ----------------------------------------------------------------------------------- | ----------------- | ---- | --- | ------- | -------------- | @@ -37,12 +35,13 @@ Fields | embed-html | HTML embed code for this media | text | YES | | NULL | | | embed-height | Height of the embed | smallint unsigned | YES | | NULL | | | embed-width | Width of the embed | smallint unsigned | YES | | NULL | | +| page-type | Type of the page (e.g. article, website) | varchar(30) | YES | | NULL | | +| schematypes | Schema types of the page as JSON string | varchar(255) | YES | | NULL | | | language | Language information about this media in the ISO 639 format | char(3) | YES | | NULL | | | published | Publification date of this media | datetime | YES | | NULL | | | modified | Modification date of this media | datetime | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------------ | ------------------------ | @@ -52,13 +51,12 @@ Indexes | media-uri-id | media-uri-id | | attach-id | attach-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| media-uri-id | [item-uri](help/database/db_item-uri) | id | -| attach-id | [attach](help/database/db_attach) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| media-uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| attach-id | [attach](help/spec/database/db-attach) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-origin.md b/doc/en/spec/database/db-post-origin.md similarity index 85% rename from doc/database/db_post-origin.md rename to doc/en/spec/database/db-post-origin.md index dc72b0134f..5416651caa 100644 --- a/doc/database/db_post-origin.md +++ b/doc/en/spec/database/db-post-origin.md @@ -1,10 +1,8 @@ -Table post-origin -=========== +# Table post-origin Posts from local users -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | ------------------------------------------------------------ | ------------------ | ---- | --- | ------------------- | ----- | @@ -20,8 +18,7 @@ Fields | private | 0=public, 1=private, 2=unlisted | tinyint unsigned | NO | | 0 | | | wall | This item was posted to the wall of uid | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ----------------- | ------------------- | @@ -34,15 +31,14 @@ Indexes | parent-uri-id_uid | parent-uri-id, uid | | uid_wall_received | uid, wall, received | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| uid | [user](help/database/db_user) | uid | -| parent-uri-id | [item-uri](help/database/db_item-uri) | id | -| thr-parent-id | [item-uri](help/database/db_item-uri) | id | -| vid | [verb](help/database/db_verb) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | +| parent-uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| thr-parent-id | [item-uri](help/spec/database/db-item-uri) | id | +| vid | [verb](help/spec/database/db-verb) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-question-option.md b/doc/en/spec/database/db-post-question-option.md similarity index 81% rename from doc/database/db_post-question-option.md rename to doc/en/spec/database/db-post-question-option.md index 0dd10acabf..a8d350c571 100644 --- a/doc/database/db_post-question-option.md +++ b/doc/en/spec/database/db-post-question-option.md @@ -1,10 +1,8 @@ -Table post-question-option -=========== +# Table post-question-option Question option -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | --------------------------------------------------------- | ------------ | ---- | --- | ------- | ----- | @@ -13,18 +11,16 @@ Fields | name | Name of the option | varchar(255) | YES | | NULL | | | replies | Number of replies for this question option | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ---------- | | PRIMARY | uri-id, id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-question.md b/doc/en/spec/database/db-post-question.md similarity index 85% rename from doc/database/db_post-question.md rename to doc/en/spec/database/db-post-question.md index 8f637ffcf3..776a215b88 100644 --- a/doc/database/db_post-question.md +++ b/doc/en/spec/database/db-post-question.md @@ -1,10 +1,8 @@ -Table post-question -=========== +# Table post-question Question -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | --------------------------------------------------------- | ------------ | ---- | --- | ------------------- | -------------- | @@ -14,19 +12,17 @@ Fields | voters | Number of voters for this question | int unsigned | YES | | NULL | | | end-time | Question end time | datetime | YES | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | -------------- | | PRIMARY | id | | uri-id | UNIQUE, uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-searchindex.md b/doc/en/spec/database/db-post-searchindex.md similarity index 86% rename from doc/database/db_post-searchindex.md rename to doc/en/spec/database/db-post-searchindex.md index 203a2dbab3..9e2ef0b4dd 100644 --- a/doc/database/db_post-searchindex.md +++ b/doc/en/spec/database/db-post-searchindex.md @@ -1,10 +1,8 @@ -Table post-searchindex -=========== +# Table post-searchindex Content for all posts -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ---------- | --------------------------------------------------------------------- | ------------ | ---- | --- | ------- | ----- | @@ -17,8 +15,7 @@ Fields | created | | datetime | YES | | NULL | | | restricted | If true, this post is either unlisted or not from a federated network | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | -------------------- | @@ -27,12 +24,11 @@ Indexes | created | created | | searchtext | FULLTEXT, searchtext | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| owner-id | [contact](help/database/db_contact) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| owner-id | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-tag.md b/doc/en/spec/database/db-post-tag.md similarity index 77% rename from doc/database/db_post-tag.md rename to doc/en/spec/database/db-post-tag.md index 7811f32e07..b57cf919df 100644 --- a/doc/database/db_post-tag.md +++ b/doc/en/spec/database/db-post-tag.md @@ -1,10 +1,8 @@ -Table post-tag -=========== +# Table post-tag post relation to tags -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------ | --------------------------------------------------------- | ---------------- | ---- | --- | ------- | ----- | @@ -13,8 +11,7 @@ Fields | tid | | int unsigned | NO | PRI | 0 | | | cid | Contact id of the mentioned public contact | int unsigned | NO | PRI | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ---------------------- | @@ -22,13 +19,12 @@ Indexes | tid | tid | | cid | cid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| tid | [tag](help/database/db_tag) | id | -| cid | [contact](help/database/db_contact) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| tid | [tag](help/spec/database/db-tag) | id | +| cid | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-thread-user.md b/doc/en/spec/database/db-post-thread-user.md similarity index 89% rename from doc/database/db_post-thread-user.md rename to doc/en/spec/database/db-post-thread-user.md index d00e852547..06f5567f35 100644 --- a/doc/database/db_post-thread-user.md +++ b/doc/en/spec/database/db-post-thread-user.md @@ -1,10 +1,8 @@ -Table post-thread-user -=========== +# Table post-thread-user Thread related data per user -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------- | ------------------------------------------------------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | ----- | @@ -34,8 +32,7 @@ Fields | psid | ID of the permission set of this post | int unsigned | YES | | NULL | | | post-user-id | Id of the post-user table | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | -------------------- | --------------------- | @@ -64,20 +61,19 @@ Indexes | contact-id_received | contact-id, received | | contact-id_created | contact-id, created | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| context-id | [item-uri](help/database/db_item-uri) | id | -| conversation-id | [item-uri](help/database/db_item-uri) | id | -| owner-id | [contact](help/database/db_contact) | id | -| author-id | [contact](help/database/db_contact) | id | -| causer-id | [contact](help/database/db_contact) | id | -| uid | [user](help/database/db_user) | uid | -| contact-id | [contact](help/database/db_contact) | id | -| psid | [permissionset](help/database/db_permissionset) | id | -| post-user-id | [post-user](help/database/db_post-user) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| context-id | [item-uri](help/spec/database/db-item-uri) | id | +| conversation-id | [item-uri](help/spec/database/db-item-uri) | id | +| owner-id | [contact](help/spec/database/db-contact) | id | +| author-id | [contact](help/spec/database/db-contact) | id | +| causer-id | [contact](help/spec/database/db-contact) | id | +| uid | [user](help/spec/database/db-user) | uid | +| contact-id | [contact](help/spec/database/db-contact) | id | +| psid | [permissionset](help/spec/database/db-permissionset) | id | +| post-user-id | [post-user](help/spec/database/db-post-user) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-thread.md b/doc/en/spec/database/db-post-thread.md similarity index 85% rename from doc/database/db_post-thread.md rename to doc/en/spec/database/db-post-thread.md index 959927a468..fcd146b16d 100644 --- a/doc/database/db_post-thread.md +++ b/doc/en/spec/database/db-post-thread.md @@ -1,10 +1,8 @@ -Table post-thread -=========== +# Table post-thread Thread related data -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------- | ------------------------------------------------------------------------------------------------------- | ------------ | ---- | --- | ------------------- | ----- | @@ -20,8 +18,7 @@ Fields | changed | Date that something in the conversation changed, indicating clients should fetch the conversation again | datetime | NO | | 0001-01-01 00:00:00 | | | commented | | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | --------------- | --------------- | @@ -34,16 +31,15 @@ Indexes | received | received | | commented | commented | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| context-id | [item-uri](help/database/db_item-uri) | id | -| conversation-id | [item-uri](help/database/db_item-uri) | id | -| owner-id | [contact](help/database/db_contact) | id | -| author-id | [contact](help/database/db_contact) | id | -| causer-id | [contact](help/database/db_contact) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| context-id | [item-uri](help/spec/database/db-item-uri) | id | +| conversation-id | [item-uri](help/spec/database/db-item-uri) | id | +| owner-id | [contact](help/spec/database/db-contact) | id | +| author-id | [contact](help/spec/database/db-contact) | id | +| causer-id | [contact](help/spec/database/db-contact) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-user-notification.md b/doc/en/spec/database/db-post-user-notification.md similarity index 77% rename from doc/database/db_post-user-notification.md rename to doc/en/spec/database/db-post-user-notification.md index 8f9925b19c..0f34edf54a 100644 --- a/doc/database/db_post-user-notification.md +++ b/doc/en/spec/database/db-post-user-notification.md @@ -1,10 +1,8 @@ -Table post-user-notification -=========== +# Table post-user-notification User post notifications -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----------------- | --------------------------------------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -12,20 +10,18 @@ Fields | uid | Owner id which owns this copy of the item | mediumint unsigned | NO | PRI | NULL | | | notification-type | | smallint unsigned | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ----------- | | PRIMARY | uid, uri-id | | uri-id | uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| uid | [user](help/database/db_user) | uid | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post-user.md b/doc/en/spec/database/db-post-user.md similarity index 89% rename from doc/database/db_post-user.md rename to doc/en/spec/database/db-post-user.md index 502c49c3ac..94936cde08 100644 --- a/doc/database/db_post-user.md +++ b/doc/en/spec/database/db-post-user.md @@ -1,10 +1,8 @@ -Table post-user -=========== +# Table post-user User specific post data -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- | --- | ------------------- | -------------- | @@ -41,8 +39,7 @@ Fields | origin | item originated at this site | boolean | NO | | 0 | | | psid | ID of the permission set of this post | int unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | --------------------- | ----------------------- | @@ -70,23 +67,22 @@ Indexes | uid_unseen | uid, unseen | | uid_hidden_uri-id | uid, hidden, uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| parent-uri-id | [item-uri](help/database/db_item-uri) | id | -| thr-parent-id | [item-uri](help/database/db_item-uri) | id | -| external-id | [item-uri](help/database/db_item-uri) | id | -| replies-id | [item-uri](help/database/db_item-uri) | id | -| owner-id | [contact](help/database/db_contact) | id | -| author-id | [contact](help/database/db_contact) | id | -| causer-id | [contact](help/database/db_contact) | id | -| vid | [verb](help/database/db_verb) | id | -| uid | [user](help/database/db_user) | uid | -| contact-id | [contact](help/database/db_contact) | id | -| event-id | [event](help/database/db_event) | id | -| psid | [permissionset](help/database/db_permissionset) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| parent-uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| thr-parent-id | [item-uri](help/spec/database/db-item-uri) | id | +| external-id | [item-uri](help/spec/database/db-item-uri) | id | +| replies-id | [item-uri](help/spec/database/db-item-uri) | id | +| owner-id | [contact](help/spec/database/db-contact) | id | +| author-id | [contact](help/spec/database/db-contact) | id | +| causer-id | [contact](help/spec/database/db-contact) | id | +| vid | [verb](help/spec/database/db-verb) | id | +| uid | [user](help/spec/database/db-user) | uid | +| contact-id | [contact](help/spec/database/db-contact) | id | +| event-id | [event](help/spec/database/db-event) | id | +| psid | [permissionset](help/spec/database/db-permissionset) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_post.md b/doc/en/spec/database/db-post.md similarity index 85% rename from doc/database/db_post.md rename to doc/en/spec/database/db-post.md index 8f6690be06..2413e61928 100644 --- a/doc/database/db_post.md +++ b/doc/en/spec/database/db-post.md @@ -1,10 +1,8 @@ -Table post -=========== +# Table post Structure for all posts -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------- | ------------------------------------------------------------------------------------ | ----------------- | ---- | --- | ------------------- | ----- | @@ -28,8 +26,7 @@ Fields | visible | | boolean | NO | | 0 | | | deleted | item has been marked for deletion | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------------- | ------------- | @@ -43,19 +40,18 @@ Indexes | causer-id | causer-id | | vid | vid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uri-id | [item-uri](help/database/db_item-uri) | id | -| parent-uri-id | [item-uri](help/database/db_item-uri) | id | -| thr-parent-id | [item-uri](help/database/db_item-uri) | id | -| external-id | [item-uri](help/database/db_item-uri) | id | -| replies-id | [item-uri](help/database/db_item-uri) | id | -| owner-id | [contact](help/database/db_contact) | id | -| author-id | [contact](help/database/db_contact) | id | -| causer-id | [contact](help/database/db_contact) | id | -| vid | [verb](help/database/db_verb) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| parent-uri-id | [item-uri](help/spec/database/db-item-uri) | id | +| thr-parent-id | [item-uri](help/spec/database/db-item-uri) | id | +| external-id | [item-uri](help/spec/database/db-item-uri) | id | +| replies-id | [item-uri](help/spec/database/db-item-uri) | id | +| owner-id | [contact](help/spec/database/db-contact) | id | +| author-id | [contact](help/spec/database/db-contact) | id | +| causer-id | [contact](help/spec/database/db-contact) | id | +| vid | [verb](help/spec/database/db-verb) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_process.md b/doc/en/spec/database/db-process.md similarity index 88% rename from doc/database/db_process.md rename to doc/en/spec/database/db-process.md index b1a52e01b7..5f73400abd 100644 --- a/doc/database/db_process.md +++ b/doc/en/spec/database/db-process.md @@ -1,10 +1,8 @@ -Table process -=========== +# Table process Currently running system processes -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | ------------------------------------------ | ------------- | ---- | --- | ------------------- | ----- | @@ -13,8 +11,7 @@ Fields | command | | varbinary(32) | NO | | | | | created | | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------------- | @@ -22,4 +19,4 @@ Indexes | command | command | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_profile.md b/doc/en/spec/database/db-profile.md similarity index 97% rename from doc/database/db_profile.md rename to doc/en/spec/database/db-profile.md index 09f10770be..176b81082d 100644 --- a/doc/database/db_profile.md +++ b/doc/en/spec/database/db-profile.md @@ -1,10 +1,8 @@ -Table profile -=========== +# Table profile user profiles data -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----------------- | -------------------------------------------------------------- | ------------------ | ---- | --- | ---------- | -------------- | @@ -53,19 +51,17 @@ Fields | publish | publish default profile in local directory | boolean | NO | | 0 | | | net-publish | publish profile in global directory | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | -------------- | --------------- | | PRIMARY | id | | uid_is-default | uid, is-default | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_profile_field.md b/doc/en/spec/database/db-profile_field.md similarity index 87% rename from doc/database/db_profile_field.md rename to doc/en/spec/database/db-profile_field.md index 56e8e3d0b6..c8220a9047 100644 --- a/doc/database/db_profile_field.md +++ b/doc/en/spec/database/db-profile_field.md @@ -1,10 +1,8 @@ -Table profile_field -=========== +# Table profile_field Custom profile fields -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ----------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -17,8 +15,7 @@ Fields | created | creation time | datetime | NO | | 0001-01-01 00:00:00 | | | edited | last edit time | datetime | NO | | 0001-01-01 00:00:00 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | @@ -27,12 +24,11 @@ Indexes | order | order | | psid | psid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| psid | [permissionset](help/database/db_permissionset) | id | +| uid | [user](help/spec/database/db-user) | uid | +| psid | [permissionset](help/spec/database/db-permissionset) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_register.md b/doc/en/spec/database/db-register.md similarity index 85% rename from doc/database/db_register.md rename to doc/en/spec/database/db-register.md index 15d7c03dc3..100778ca5d 100644 --- a/doc/database/db_register.md +++ b/doc/en/spec/database/db-register.md @@ -1,10 +1,8 @@ -Table register -=========== +# Table register registrations requiring admin approval -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | ------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -16,19 +14,17 @@ Fields | language | | varchar(16) | NO | | | | | note | | text | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | id | | uid | uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_report-post.md b/doc/en/spec/database/db-report-post.md similarity index 73% rename from doc/database/db_report-post.md rename to doc/en/spec/database/db-report-post.md index d005b31e34..ed94584a32 100644 --- a/doc/database/db_report-post.md +++ b/doc/en/spec/database/db-report-post.md @@ -1,10 +1,8 @@ -Table report-post -=========== +# Table report-post Individual posts attached to a moderation report -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------ | --------------------------- | ---------------- | ---- | --- | ------- | ----- | @@ -12,20 +10,18 @@ Fields | uri-id | Uri-id of the reported post | int unsigned | NO | PRI | NULL | | | status | Status of the reported post | tinyint unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ----------- | | PRIMARY | rid, uri-id | | uri-id | uri-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| rid | [report](help/database/db_report) | id | -| uri-id | [item-uri](help/database/db_item-uri) | id | +| rid | [report](help/spec/database/db-report) | id | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_report-rule.md b/doc/en/spec/database/db-report-rule.md similarity index 82% rename from doc/database/db_report-rule.md rename to doc/en/spec/database/db-report-rule.md index f82d757eb5..1ac28f02ee 100644 --- a/doc/database/db_report-rule.md +++ b/doc/en/spec/database/db-report-rule.md @@ -1,10 +1,8 @@ -Table report-rule -=========== +# Table report-rule Terms of service rule lines relevant to a moderation report -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ------------------------------------------------------------------------- | ------------ | ---- | --- | ------- | ----- | @@ -12,18 +10,16 @@ Fields | line-id | Terms of service rule line number, may become invalid after a TOS change. | int unsigned | NO | PRI | NULL | | | text | Terms of service rule text recorded at the time of the report | text | NO | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------------ | | PRIMARY | rid, line-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| rid | [report](help/database/db_report) | id | +| rid | [report](help/spec/database/db-report) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_report.md b/doc/en/spec/database/db-report.md similarity index 88% rename from doc/database/db_report.md rename to doc/en/spec/database/db-report.md index 7157224314..d888785600 100644 --- a/doc/database/db_report.md +++ b/doc/en/spec/database/db-report.md @@ -1,10 +1,8 @@ -Table report -=========== +# Table report -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------------- | ------------------------------------------------------------ | ------------------ | ---- | --- | -------------------------- | -------------- | @@ -25,8 +23,7 @@ Fields | created | | datetime(6) | NO | | 0001-01-01 00:00:00.000000 | | | edited | Last time the report has been edited | datetime(6) | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ----------------- | ------------------ | @@ -41,16 +38,15 @@ Indexes | created | created | | edited | edited | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| reporter-id | [contact](help/database/db_contact) | id | -| cid | [contact](help/database/db_contact) | id | -| gsid | [gserver](help/database/db_gserver) | id | -| last-editor-uid | [user](help/database/db_user) | uid | -| assigned-uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | +| reporter-id | [contact](help/spec/database/db-contact) | id | +| cid | [contact](help/spec/database/db-contact) | id | +| gsid | [gserver](help/spec/database/db-gserver) | id | +| last-editor-uid | [user](help/spec/database/db-user) | uid | +| assigned-uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_search.md b/doc/en/spec/database/db-search.md similarity index 78% rename from doc/database/db_search.md rename to doc/en/spec/database/db-search.md index 157d09ecb8..69f3b1ac77 100644 --- a/doc/database/db_search.md +++ b/doc/en/spec/database/db-search.md @@ -1,10 +1,8 @@ -Table search -=========== +# Table search -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ------------- | ------------------ | ---- | --- | ------- | -------------- | @@ -12,8 +10,7 @@ Fields | uid | User id | mediumint unsigned | NO | | 0 | | | term | | varchar(255) | NO | | | | -Indexes ------------- +## Indexes | Name | Fields | | -------- | ------------- | @@ -21,11 +18,10 @@ Indexes | uid_term | uid, term(64) | | term | term(64) | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_session.md b/doc/en/spec/database/db-session.md similarity index 85% rename from doc/database/db_session.md rename to doc/en/spec/database/db-session.md index 794e49c6a7..6d5c92b543 100644 --- a/doc/database/db_session.md +++ b/doc/en/spec/database/db-session.md @@ -1,10 +1,8 @@ -Table session -=========== +# Table session web session storage -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------ | ------------- | --------------- | ---- | --- | ------- | -------------- | @@ -13,8 +11,7 @@ Fields | data | | text | YES | | NULL | | | expire | | int unsigned | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------- | @@ -23,4 +20,4 @@ Indexes | expire | expire | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_storage.md b/doc/en/spec/database/db-storage.md similarity index 81% rename from doc/database/db_storage.md rename to doc/en/spec/database/db-storage.md index 55911e28a6..7f10a8c93e 100644 --- a/doc/database/db_storage.md +++ b/doc/en/spec/database/db-storage.md @@ -1,22 +1,19 @@ -Table storage -=========== +# Table storage Data stored by Database storage backend -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ------------------------------ | ------------ | ---- | --- | ------- | -------------- | | id | Auto incremented image data id | int unsigned | NO | PRI | NULL | auto_increment | | data | file data | longblob | NO | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_subscription.md b/doc/en/spec/database/db-subscription.md similarity index 88% rename from doc/database/db_subscription.md rename to doc/en/spec/database/db-subscription.md index 8bcf4f2379..7f6c9a093d 100644 --- a/doc/database/db_subscription.md +++ b/doc/en/spec/database/db-subscription.md @@ -1,10 +1,8 @@ -Table subscription -=========== +# Table subscription Push Subscription for the API -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------------- | ------------------------------ | ------------------ | ---- | --- | ------- | -------------- | @@ -22,8 +20,7 @@ Fields | follow_request | | boolean | YES | | NULL | | | status | | boolean | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------------------ | --------------------------- | @@ -31,12 +28,11 @@ Indexes | application-id_uid | UNIQUE, application-id, uid | | uid_application-id | uid, application-id | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| application-id | [application](help/database/db_application) | id | -| uid | [user](help/database/db_user) | uid | +| application-id | [application](help/spec/database/db-application) | id | +| uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_tag.md b/doc/en/spec/database/db-tag.md similarity index 91% rename from doc/database/db_tag.md rename to doc/en/spec/database/db-tag.md index 5b50cdf902..d6c54fe560 100644 --- a/doc/database/db_tag.md +++ b/doc/en/spec/database/db-tag.md @@ -1,10 +1,8 @@ -Table tag -=========== +# Table tag tags and mentions -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ----------------------------------------------------------------------------- | ---------------- | ---- | --- | ------- | -------------- | @@ -13,8 +11,7 @@ Fields | url | | varbinary(383) | NO | | | | | type | Type of the tag (Unknown, General Collection, Follower Collection or Account) | tinyint unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------------- | ----------------- | @@ -23,4 +20,4 @@ Indexes | url | url | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_user-contact.md b/doc/en/spec/database/db-user-contact.md similarity index 93% rename from doc/database/db_user-contact.md rename to doc/en/spec/database/db-user-contact.md index e52d8d495c..618995b9fb 100644 --- a/doc/database/db_user-contact.md +++ b/doc/en/spec/database/db-user-contact.md @@ -1,10 +1,8 @@ -Table user-contact -=========== +# Table user-contact User specific public contact data -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------------------- | -------------------------------------------------------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -30,8 +28,7 @@ Fields | rating | Automatically detected feed poll frequency | tinyint | YES | | NULL | | | priority | Feed poll priority | tinyint unsigned | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | ------------------- | @@ -39,13 +36,12 @@ Indexes | cid | cid | | uri-id_uid | UNIQUE, uri-id, uid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| cid | [contact](help/database/db_contact) | id | -| uid | [user](help/database/db_user) | uid | -| uri-id | [item-uri](help/database/db_item-uri) | id | +| cid | [contact](help/spec/database/db-contact) | id | +| uid | [user](help/spec/database/db-user) | uid | +| uri-id | [item-uri](help/spec/database/db-item-uri) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_user-gserver.md b/doc/en/spec/database/db-user-gserver.md similarity index 75% rename from doc/database/db_user-gserver.md rename to doc/en/spec/database/db-user-gserver.md index 7ad6de485e..287d128c95 100644 --- a/doc/database/db_user-gserver.md +++ b/doc/en/spec/database/db-user-gserver.md @@ -1,10 +1,8 @@ -Table user-gserver -=========== +# Table user-gserver User settings about remote servers -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------- | ---------------------------------------- | ------------------ | ---- | --- | ------- | ----- | @@ -12,20 +10,18 @@ Fields | gsid | Gserver id | int unsigned | NO | PRI | 0 | | | ignored | server accounts are ignored for the user | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | --------- | | PRIMARY | uid, gsid | | gsid | gsid | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| uid | [user](help/database/db_user) | uid | -| gsid | [gserver](help/database/db_gserver) | id | +| uid | [user](help/spec/database/db-user) | uid | +| gsid | [gserver](help/spec/database/db-gserver) | id | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_user.md b/doc/en/spec/database/db-user.md similarity index 97% rename from doc/database/db_user.md rename to doc/en/spec/database/db-user.md index eb8ed06532..e1fa7e064a 100644 --- a/doc/database/db_user.md +++ b/doc/en/spec/database/db-user.md @@ -1,10 +1,8 @@ -Table user -=========== +# Table user The local users -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ------------------------ | --------------------------------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- | @@ -51,8 +49,7 @@ Fields | deny_gid | default permission for this user | mediumtext | YES | | NULL | | | openidserver | | text | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ---------- | ------------ | @@ -62,11 +59,10 @@ Indexes | guid | guid | | email | email(64) | -Foreign Keys ------------- +## Foreign keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| parent-uid | [user](help/database/db_user) | uid | +| parent-uid | [user](help/spec/database/db-user) | uid | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_userd.md b/doc/en/spec/database/db-userd.md similarity index 81% rename from doc/database/db_userd.md rename to doc/en/spec/database/db-userd.md index 17a81b408a..b141165fc3 100644 --- a/doc/database/db_userd.md +++ b/doc/en/spec/database/db-userd.md @@ -1,18 +1,15 @@ -Table userd -=========== +# Table userd Deleted usernames -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | -------- | ------------- | ------------ | ---- | --- | ------- | -------------- | | id | sequential ID | int unsigned | NO | PRI | NULL | auto_increment | | username | | varchar(255) | NO | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | -------- | ------------ | @@ -20,4 +17,4 @@ Indexes | username | username(32) | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_verb.md b/doc/en/spec/database/db-verb.md similarity index 80% rename from doc/database/db_verb.md rename to doc/en/spec/database/db-verb.md index 43507053b2..b837e43594 100644 --- a/doc/database/db_verb.md +++ b/doc/en/spec/database/db-verb.md @@ -1,18 +1,15 @@ -Table verb -=========== +# Table verb Activity Verbs -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ----------- | ----------------- | ---- | --- | ------- | -------------- | | id | | smallint unsigned | NO | PRI | NULL | auto_increment | | name | | varchar(100) | NO | | | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | @@ -20,4 +17,4 @@ Indexes | name | name | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_worker-ipc.md b/doc/en/spec/database/db-worker-ipc.md similarity index 79% rename from doc/database/db_worker-ipc.md rename to doc/en/spec/database/db-worker-ipc.md index 1635981d70..5df3e467d7 100644 --- a/doc/database/db_worker-ipc.md +++ b/doc/en/spec/database/db-worker-ipc.md @@ -1,22 +1,19 @@ -Table worker-ipc -=========== +# Table worker-ipc Inter process communication between the frontend and the worker -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | ----- | ------------------------- | ------- | ---- | --- | ------- | ----- | | key | | int | NO | PRI | NULL | | | jobs | Flag for outstanding jobs | boolean | YES | | NULL | | -Indexes ------------- +## Indexes | Name | Fields | | ------- | ------ | | PRIMARY | key | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/database/db_workerqueue.md b/doc/en/spec/database/db-workerqueue.md similarity index 95% rename from doc/database/db_workerqueue.md rename to doc/en/spec/database/db-workerqueue.md index a479ecbcaa..970ef77a5b 100644 --- a/doc/database/db_workerqueue.md +++ b/doc/en/spec/database/db-workerqueue.md @@ -1,10 +1,8 @@ -Table workerqueue -=========== +# Table workerqueue Background tasks queue entries -Fields ------- +## Fields | Field | Description | Type | Null | Key | Default | Extra | | --------- | ------------------------------------------------------- | ---------------- | ---- | --- | ------------------- | -------------- | @@ -19,8 +17,7 @@ Fields | retrial | Retrial counter | tinyint | NO | | 0 | | | done | Marked 1 when the task was done - will be deleted later | boolean | NO | | 0 | | -Indexes ------------- +## Indexes | Name | Fields | | ----------------------------- | -------------------------------- | @@ -35,4 +32,4 @@ Indexes | done_pid_priority_created | done, pid, priority, created | -Return to [database documentation](help/database) +Return to [database documentation](help/spec/database/index) diff --git a/doc/en/spec/database/index.md b/doc/en/spec/database/index.md new file mode 100644 index 0000000000..8c538cfe78 --- /dev/null +++ b/doc/en/spec/database/index.md @@ -0,0 +1,94 @@ +# Database tables + +| Table | Description | +|-------|-------------| +| [2fa_app_specific_password](help/spec/database/db-2fa_app_specific_password) | Two-factor app-specific _password | +| [2fa_recovery_codes](help/spec/database/db-2fa_recovery_codes) | Two-factor authentication recovery codes | +| [2fa_trusted_browser](help/spec/database/db-2fa_trusted_browser) | Two-factor authentication trusted browsers | +| [account-suggestion](help/spec/database/db-account-suggestion) | Account suggestion | +| [account-user](help/spec/database/db-account-user) | Remote and local accounts | +| [apcontact](help/spec/database/db-apcontact) | ActivityPub compatible contacts - used in the ActivityPub implementation | +| [application](help/spec/database/db-application) | OAuth application | +| [application-marker](help/spec/database/db-application-marker) | Timeline marker | +| [application-token](help/spec/database/db-application-token) | OAuth user token | +| [arrived-activity](help/spec/database/db-arrived-activity) | Id of arrived activities | +| [attach](help/spec/database/db-attach) | file attachments | +| [cache](help/spec/database/db-cache) | Stores temporary data | +| [channel](help/spec/database/db-channel) | User defined Channels | +| [check-full-text-search](help/spec/database/db-check-full-text-search) | Check for a full text search match in user defined channels before storing the message in the system | +| [config](help/spec/database/db-config) | main configuration storage | +| [contact](help/spec/database/db-contact) | contact table | +| [contact-relation](help/spec/database/db-contact-relation) | Contact relations | +| [conv](help/spec/database/db-conv) | private messages | +| [delayed-post](help/spec/database/db-delayed-post) | Posts that are about to be distributed at a later time | +| [delivery-queue](help/spec/database/db-delivery-queue) | Delivery data for posts for the batch processing | +| [diaspora-contact](help/spec/database/db-diaspora-contact) | Diaspora compatible contacts - used in the Diaspora implementation | +| [diaspora-interaction](help/spec/database/db-diaspora-interaction) | Signed Diaspora Interaction | +| [endpoint](help/spec/database/db-endpoint) | ActivityPub endpoints - used in the ActivityPub implementation | +| [event](help/spec/database/db-event) | Events | +| [fetch-entry](help/spec/database/db-fetch-entry) | | +| [fetched-activity](help/spec/database/db-fetched-activity) | Id of fetched activities | +| [fsuggest](help/spec/database/db-fsuggest) | friend suggestion stuff | +| [group](help/spec/database/db-group) | privacy circles, circle info | +| [group_member](help/spec/database/db-group_member) | privacy circles, member info | +| [gserver](help/spec/database/db-gserver) | Global servers | +| [gserver-tag](help/spec/database/db-gserver-tag) | Tags that the server has subscribed | +| [hook](help/spec/database/db-hook) | addon hook registry | +| [inbox-entry](help/spec/database/db-inbox-entry) | Incoming activity | +| [inbox-entry-receiver](help/spec/database/db-inbox-entry-receiver) | Receiver for the incoming activity | +| [inbox-status](help/spec/database/db-inbox-status) | Status of ActivityPub inboxes | +| [intro](help/spec/database/db-intro) | | +| [item-uri](help/spec/database/db-item-uri) | URI and GUID for items | +| [key-value](help/spec/database/db-key-value) | A key value storage | +| [locks](help/spec/database/db-locks) | | +| [mail](help/spec/database/db-mail) | private messages | +| [mailacct](help/spec/database/db-mailacct) | Mail account data for fetching mails | +| [manage](help/spec/database/db-manage) | table of accounts that can manage each other | +| [notification](help/spec/database/db-notification) | notifications | +| [notify](help/spec/database/db-notify) | [Deprecated] User notifications | +| [notify-threads](help/spec/database/db-notify-threads) | | +| [openwebauth-token](help/spec/database/db-openwebauth-token) | Store OpenWebAuth token to verify contacts | +| [parsed_url](help/spec/database/db-parsed_url) | cache for 'parse_url' queries | +| [pconfig](help/spec/database/db-pconfig) | personal (per user) configuration storage | +| [permissionset](help/spec/database/db-permissionset) | | +| [photo](help/spec/database/db-photo) | photo storage | +| [post](help/spec/database/db-post) | Structure for all posts | +| [post-activity](help/spec/database/db-post-activity) | Original remote activity | +| [post-category](help/spec/database/db-post-category) | post relation to categories | +| [post-collection](help/spec/database/db-post-collection) | Collection of posts | +| [post-content](help/spec/database/db-post-content) | Content for all posts | +| [post-counts](help/spec/database/db-post-counts) | Original remote activity | +| [post-delivery](help/spec/database/db-post-delivery) | Delivery data for posts for the batch processing | +| [post-delivery-data](help/spec/database/db-post-delivery-data) | Delivery data for items | +| [post-engagement](help/spec/database/db-post-engagement) | Engagement data per post | +| [post-history](help/spec/database/db-post-history) | Post history | +| [post-link](help/spec/database/db-post-link) | Post related external links | +| [post-media](help/spec/database/db-post-media) | Attached media | +| [post-origin](help/spec/database/db-post-origin) | Posts from local users | +| [post-question](help/spec/database/db-post-question) | Question | +| [post-question-option](help/spec/database/db-post-question-option) | Question option | +| [post-searchindex](help/spec/database/db-post-searchindex) | Content for all posts | +| [post-tag](help/spec/database/db-post-tag) | post relation to tags | +| [post-thread](help/spec/database/db-post-thread) | Thread related data | +| [post-thread-user](help/spec/database/db-post-thread-user) | Thread related data per user | +| [post-user](help/spec/database/db-post-user) | User specific post data | +| [post-user-notification](help/spec/database/db-post-user-notification) | User post notifications | +| [process](help/spec/database/db-process) | Currently running system processes | +| [profile](help/spec/database/db-profile) | user profiles data | +| [profile_field](help/spec/database/db-profile_field) | Custom profile fields | +| [register](help/spec/database/db-register) | registrations requiring admin approval | +| [report](help/spec/database/db-report) | | +| [report-post](help/spec/database/db-report-post) | Individual posts attached to a moderation report | +| [report-rule](help/spec/database/db-report-rule) | Terms of service rule lines relevant to a moderation report | +| [search](help/spec/database/db-search) | | +| [session](help/spec/database/db-session) | web session storage | +| [storage](help/spec/database/db-storage) | Data stored by Database storage backend | +| [subscription](help/spec/database/db-subscription) | Push Subscription for the API | +| [tag](help/spec/database/db-tag) | tags and mentions | +| [user](help/spec/database/db-user) | The local users | +| [user-contact](help/spec/database/db-user-contact) | User specific public contact data | +| [user-gserver](help/spec/database/db-user-gserver) | User settings about remote servers | +| [userd](help/spec/database/db-userd) | Deleted usernames | +| [verb](help/spec/database/db-verb) | Activity Verbs | +| [worker-ipc](help/spec/database/db-worker-ipc) | Inter process communication between the frontend and the worker | +| [workerqueue](help/spec/database/db-workerqueue) | Background tasks queue entries | diff --git a/doc/Message-Flow.md b/doc/en/spec/message-flow.md similarity index 83% rename from doc/Message-Flow.md rename to doc/en/spec/message-flow.md index e967985695..9bf8f8f8c8 100644 --- a/doc/Message-Flow.md +++ b/doc/en/spec/message-flow.md @@ -1,5 +1,4 @@ -Friendica Message Flow -=== +# Friendica message flow This page documents some of the details of how messages get from one person to another in the Friendica network. There are multiple paths, using multiple protocols and message formats. @@ -11,7 +10,7 @@ This file also invokes the local side of all deliveries including DFRN-notify. mod/dfrn_notify.php handles the remote side of DFRN-notify. -Local feeds are generated by mod/dfrn_poll.php - which also handles the remote side of DFRN-poll protocol. +Local feeds are generated by mod/dfrn_poll.php - which also handles the remote side of DFRN-poll protocol. Salmon notifications arrive via mod/salmon.php. @@ -19,7 +18,7 @@ Push (pubsubhubbub) feeds arrive via mod/pubsub.php DFRN-poll feed imports arrive via src/Worker/OnePoll.php as a scheduled task, this implements the local side of the DFRN-poll protocol. -### Scenario #1. Bob posts a public status message +## Scenario #1. Bob posts a public status message This is a public message with no conversation members so no private transport is used. There are two paths it can take - as a bbcode path to DFRN clients, and converted to HTML with the server's PuSH (pubsubhubbub) hubs notified. @@ -28,30 +27,30 @@ They will fall back on a daily poll in case the hub has delivery issues (this is If there is no specified hub or hubs, DFRN clients will poll at a configurable (per-contact) rate at up to 5-minute intervals. Feeds retrieved via dfrn-poll are bbcode and may also contain private conversations which the worker has permissions to see. -### Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network. +## Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network. Jack uses dfrn-notify to send a direct reply to Bob. Bob then creates a feed of the conversation and sends it to everybody involved in the conversation using dfrn-notify. PuSH hubs are notified that new content is available. -The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). +The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). -### Scenario #3. Mary replies to Bob's public message. Mary is on the Friendica/DFRN network. +## Scenario #3. Mary replies to Bob's public message. Mary is on the Friendica/DFRN network. Mary uses dfrn-notify to send a direct reply to Bob. Bob then creates a feed of the conversation and sends it to everybody involved in the conversation (excluding himself, the conversation is now sent to both Jack and Mary). Messages are sent using dfrn-notify. Push hubs are also notified that new content is available. -The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). +The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). -### Scenario #4. William replies to Bob's public message. William is on the OStatus network. +## Scenario #4. William replies to Bob's public message. William is on the OStatus network. William uses salmon to notify Bob of the reply. Content is html embedded in salmon magic envelope. Bob then creates a feed of the conversation and sends it to all Friendica participants involved in the conversation using dfrn-notify (excluding himself, the conversation is sent to both Jack and Mary). Push hubs are notified that new content is available. -The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). +The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). -### Scenario #5. Bob posts a private message to Mary and Jack. +## Scenario #5. Bob posts a private message to Mary and Jack. Message is delivered immediately to Mary and Jack using dfrn_notify. Public hubs are not notified. diff --git a/spec/dfrn-snap2.jpg b/doc/en/spec/protocol/dfrn-snap2.jpg similarity index 100% rename from spec/dfrn-snap2.jpg rename to doc/en/spec/protocol/dfrn-snap2.jpg diff --git a/spec/dfrn2.odt b/doc/en/spec/protocol/dfrn2.odt similarity index 100% rename from spec/dfrn2.odt rename to doc/en/spec/protocol/dfrn2.odt diff --git a/spec/dfrn2.pdf b/doc/en/spec/protocol/dfrn2.pdf similarity index 100% rename from spec/dfrn2.pdf rename to doc/en/spec/protocol/dfrn2.pdf diff --git a/spec/dfrn2_contact_confirmation.png b/doc/en/spec/protocol/dfrn2_contact_confirmation.png similarity index 100% rename from spec/dfrn2_contact_confirmation.png rename to doc/en/spec/protocol/dfrn2_contact_confirmation.png diff --git a/spec/dfrn2_contact_confirmation.svg b/doc/en/spec/protocol/dfrn2_contact_confirmation.svg similarity index 100% rename from spec/dfrn2_contact_confirmation.svg rename to doc/en/spec/protocol/dfrn2_contact_confirmation.svg diff --git a/spec/dfrn2_contact_request.png b/doc/en/spec/protocol/dfrn2_contact_request.png similarity index 100% rename from spec/dfrn2_contact_request.png rename to doc/en/spec/protocol/dfrn2_contact_request.png diff --git a/spec/dfrn2_contact_request.svg b/doc/en/spec/protocol/dfrn2_contact_request.svg similarity index 100% rename from spec/dfrn2_contact_request.svg rename to doc/en/spec/protocol/dfrn2_contact_request.svg diff --git a/doc/Protocol.md b/doc/en/spec/protocol/protocol.md similarity index 81% rename from doc/Protocol.md rename to doc/en/spec/protocol/protocol.md index af0002472c..be5249935c 100644 --- a/doc/Protocol.md +++ b/doc/en/spec/protocol/protocol.md @@ -1,18 +1,14 @@ -Used Protocols -=============== +# Used protocols -* [Home](help) - -Friendicas DFRN Protocol ---- +## Friendicas DFRN Protocol * [Document with the DFRN specification](spec/dfrn2.pdf) * [Schema of the contact request process](spec/dfrn2_contact_request.png) * [Schema of the contact request confirmation](spec/dfrn2_contact_confirmation.png) -* [Description of the message flow](help/Message-Flow) +* [Description of the message flow](help/spec/message-flow) + +## ActivityStreams -ActivityStreams ---- Friendica is using ActivityStreams in version 1.0 for its activities and object types. Additional types are used for non standard activities. @@ -20,8 +16,7 @@ Additional types are used for non standard activities. * [Link to the specification](http://activitystrea.ms/head/activity-schema.html) * [List of used ActivityStreams verbs and object types.](https://github.com/friendica/friendica/wiki/ActivityStreams) -Portable Contacts ---- +## Portable Contacts Portable Contacts is used for friends lists. diff --git a/spec/zot-2012.txt b/doc/en/spec/protocol/zot-2012.txt similarity index 100% rename from spec/zot-2012.txt rename to doc/en/spec/protocol/zot-2012.txt diff --git a/spec/zot.txt b/doc/en/spec/protocol/zot.txt similarity index 100% rename from spec/zot.txt rename to doc/en/spec/protocol/zot.txt diff --git a/doc/Accesskeys.md b/doc/en/user/access-keys.md similarity index 84% rename from doc/Accesskeys.md rename to doc/en/user/access-keys.md index ed0c55f7f5..2582cef8a9 100644 --- a/doc/Accesskeys.md +++ b/doc/en/user/access-keys.md @@ -1,7 +1,4 @@ -Accesskeys reference -======================= - -* [Home](help) +# Access keys reference Access keys are keyboard shortcuts that allow you to easily navigate the user interface. Access keys are currently not available with the Frio theme. @@ -12,8 +9,8 @@ For example, for moving to profile page in Firefox, press these three keys simul [Shift] [Alt] [p] -General -------- +## General + * p - Profile * n - Network * l - Channel @@ -24,13 +21,13 @@ General * f - Notifications * u - User menu -../community --------- +## ../community + * l - Local community * g - Global community -../channel --------- +## ../channel + * y - for you * f - followers * r - sharers of sharers @@ -42,8 +39,8 @@ General * g - Posts in your language * o - Hot posts in your language -../profile --------- +## ../profile + * m - Status Messages and Posts * r - Profile Details * h - Photo Albums @@ -53,8 +50,8 @@ General * o - Scheduled Posts * k - View Contacts -../contacts (contact list) ---------- +## ../contacts (contact list) + * g - Suggestions * l - Show all Contacts * o - Only show unblocked contacts @@ -64,8 +61,8 @@ General * h - Only show hidden contacts * e - Edit contact circles -../contact (single contact view) -------------------------------- +## ../contact (single contact view) + * m - Status messages * p - Posts and Comments * d - Media @@ -73,12 +70,12 @@ General * t - Contacts * r - Advanced -../message --------- +## ../message + * m - New message -../network --------- +## ../network + * e - Sort by Comment Date * t - Sort by Receipt Date * q - Sort by Creation Date @@ -86,16 +83,16 @@ General * w - New posts * m - Favourite Posts -../notifications --------------- +## ../notifications + * y - System * w - Network * r - Personal * h - Home * i - Introductions -../settings ---------- +## ../settings + * o - Account * 2 - Two-factor authentication * p - Profiles diff --git a/doc/Account-Basics.md b/doc/en/user/account-basics.md similarity index 91% rename from doc/Account-Basics.md rename to doc/en/user/account-basics.md index 975fd8fb76..39d13b84a0 100644 --- a/doc/Account-Basics.md +++ b/doc/en/user/account-basics.md @@ -1,10 +1,6 @@ -Account Basics -============== +# Account basics -* [Home](help) - -Registration ---- +## Registration Not all Friendica sites allow open registration. If registration is allowed, you will see a "Register" link immediately below the login prompt on the site's home page. @@ -46,14 +42,13 @@ It must contain only US-ASCII text characters and numbers, and must also start w It also must be unique on this system. This is used in many places to identify your account, and once set it cannot be changed. - ### Directory Publishing The registration form also allows you to choose whether or not to list your account in the online directory of your node. This is like a "phone book" and you may choose to be unlisted. We recommend that you select 'Yes' so that other people (friends, family, etc.) will be able to find you. If you choose 'No', you will essentially be invisible and have few opportunities for interaction. -Whichever you choose, this can be changed any time from your Settings page after you login. +Whichever you choose, this can be changed any time from your Settings page after you log in. ### Register @@ -61,8 +56,7 @@ Once you have provided the necessary details, click the 'Register' button. An email will be sent to you providing your account login details. Please check your email (including spam folders) for your registration details and initial password. -Login Page ---- +## Login Page On the 'Login' page, please enter your login information that was provided during registration. You may use either your nickname or email address as a Login Name. @@ -76,34 +70,25 @@ Otherwise, enter your password. This will have been initially provided in your registration email message. Your password is case-sensitive, so please check your 'Caps Lock' key if you are having difficulty logging in. -Changing Your Password ---- +## Changing Your Password After your first login, please visit the 'Settings' page from the top menu bar and change your password to something that you will remember. -Getting Started ---- +## Getting Started A link with ['Tips for New Members'](newmember) will show up on your network and home pages for two weeks providing key information for getting started. -Retrieving Personal Data ---- +## Retrieving Personal Data You can export a copy of your personal data in JSON format from the "Export personal data" link at the top of your settings page. You need this file to relocate your Friendica account to another node. This might be necessary, e.g. if your node suffers a severe hardware problem and is not recoverable. -See Also ---- - -* [Profiles](help/Profiles) - -* [Global Directory](help/Making-Friends#The+Directories) - -* [Circles and Privacy](help/Circles-and-Privacy) - -* [Move Account](help/Move-Account) - -* [Remove Account](help/Remove-Account) +## See Also +- [Account types: Groups and Pages](help/user/accounts-groups-pages) +- [Global directory](help/user/making-friends#the+directories) +- [Circles and privacy](help/user/circles-and-privacy) +- [Moving an account](help/user/move-account) +- [Deleting an account](help/user/delete-account) diff --git a/doc/Groups.md b/doc/en/user/accounts-groups-pages.md similarity index 94% rename from doc/Groups.md rename to doc/en/user/accounts-groups-pages.md index 3c2e17929d..9bbabdd0ee 100644 --- a/doc/Groups.md +++ b/doc/en/user/accounts-groups-pages.md @@ -1,8 +1,4 @@ -Groups -===== - -* [Home](help) - +# Account types: Groups and pages Friendica also lets you create accounts that can function as discussion groups, celebrity accounts, announcement channels, news reflectors, or organization pages, depending on how you want to interact with others. Management of these accounts can be delegated to other accounts, or a parent account can be designated to easily toggle multiple identities. @@ -10,14 +6,13 @@ Management of these accounts can be delegated to other accounts, or a parent acc Every account in Friendica has a nickname and these must all be unique. This applies to all accounts, whether they are individual profiles or group profiles. -Managing Accounts ---- +## Managing Accounts To create a new linked account that can be used as a group, log in to your normal account and go to Settings > Manage Accounts. Here you can register additional accounts with new nicknames that will be linked to your primary account. You may appoint a delegate to manage your new account. -The Delegates section of Manage Accounts page will provide you with a list of contacts on this instance under "Potential Delegates". +The "Delegates" section of Manage Accounts page will provide you with a list of contacts on this instance under "Potential Delegates". Selecting one or more persons will give them access to manage your newly created account. They will be able to edit contacts, profiles, and all content for this account. Please use this facility wisely. @@ -26,8 +21,7 @@ Delegated managers will not be able to alter basic account settings, such as pas Additionally, this page is also where you can choose to designate an account as a parent user. If your primary account is designated as the parent user, you will be able to easily toggle identities and manage your groups or other types of accounts. -Types of Accounts ---- +## Types of Accounts On the new account, visit the Settings > Account page. Towards the end of the page is a section for "Advanced account types". @@ -47,8 +41,7 @@ Organization and New Pages automatically approve contact requests as followers. Community Group provide the ability for people to join the group without requiring approval. This creates a group where all members can freely interact. -Posting to Community groups ---- +## Posting to Community groups If you are a member of a community group, you may post to the group by including an @-mention in the post mentioning the group. For example @bicycle would send my post to all members of the group "bicycle" in addition to the normal recipients. diff --git a/doc/BBCode.md b/doc/en/user/bbcode.md similarity index 83% rename from doc/BBCode.md rename to doc/en/user/bbcode.md index a39fb20d49..6aec790d62 100644 --- a/doc/BBCode.md +++ b/doc/en/user/bbcode.md @@ -1,7 +1,6 @@ -Friendica BBCode tags reference -======================== +# Friendica BBCode tags reference -* [Creating posts](help/Text_editor) +* [Creating posts](help/user/text-editor) ## Inline @@ -61,8 +60,8 @@ table.bbcodes > * > tr > th { red - [url=http://friendi.ca]Friendica[/url] - Friendica + [url=https://friendi.ca]Friendica[/url] + Friendica [img]https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.png[/img] @@ -103,23 +102,23 @@ table.bbcodes > * > tr > th { Result - [url]http://friendi.ca[/url] - http://friendi.ca + [url]https://friendi.ca[/url] + https://friendi.ca - [url=http://friendi.ca]Friendica[/url] - Friendica + [url=https://friendi.ca]Friendica[/url] + Friendica - [bookmark]http://friendi.ca[/bookmark]

-#^[url]http://friendi.ca[/url] -

Friendica: http://friendi.ca

+ [bookmark]https://friendi.ca[/bookmark]

+#^[url]https://friendi.ca[/url] +

Friendica: https://friendi.ca

- [bookmark=http://friendi.ca]Bookmark[/bookmark]

-#^[url=http://friendi.ca]Bookmark[/url]

-#[url=http://friendi.ca]^[/url][url=http://friendi.ca]Bookmark[/url] -

Friendica: Bookmark

+ [bookmark=https://friendi.ca]Bookmark[/bookmark]

+#^[url=https://friendi.ca]Bookmark[/url]

+#[url=https://friendi.ca]^[/url][url=https://friendi.ca]Bookmark[/url] +

Friendica: Bookmark

[url=/posts/f16d77b0630f0134740c0cc47a0ea02a]Diaspora post with GUID[/url] @@ -170,7 +169,7 @@ code [code=php]function text_highlight($s,$lang)[/code]1 -
  1.  function text_highlight($s,$lang)
+
  1. function text_highlight($s,$lang)
[quote]quote[/quote] @@ -275,21 +274,21 @@ code [table]
-  [tr]
-    [th]Header 1[/th]
-    [th]Header 2[/th]
-    [th]Header 2[/th]
-  [/tr]
-  [tr]
-    [td]Cell 1[/td]
-    [td]Cell 2[/td]
-    [td]Cell 3[/td]
-  [/tr]
-  [tr]
-    [td]Cell 4[/td]
-    [td]Cell 5[/td]
-    [td]Cell 6[/td]
-  [/tr]
+ [tr]
+ [th]Header 1[/th]
+ [th]Header 2[/th]
+ [th]Header 2[/th]
+ [/tr]
+ [tr]
+ [td]Cell 1[/td]
+ [td]Cell 2[/td]
+ [td]Cell 3[/td]
+ [/tr]
+ [tr]
+ [td]Cell 4[/td]
+ [td]Cell 5[/td]
+ [td]Cell 6[/td]
+ [/tr]
[/table] @@ -372,12 +371,12 @@ code +For other networks (e.g. when you are using the "StatusNet" connector that is used to post to your GNU Social account) the general abstract element will be used.
[ul]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/ul]
[list]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/list]
    @@ -388,12 +387,12 @@ code
[ol]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/ol]
[list=1]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/list]
    @@ -404,8 +403,8 @@ code
[list=]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/list]
    @@ -416,8 +415,8 @@ code
[list=i]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/list]
    @@ -428,8 +427,8 @@ code
[list=I]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/list]
    @@ -440,8 +439,8 @@ code
[list=a]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/list]
    @@ -452,8 +451,8 @@ code
[list=A]
-  [li] First list element
-  [li] Second list element
+ [li] First list element
+ [li] Second list element
[/list]
    @@ -548,7 +547,7 @@ pictures?[/abstract]
    that I wanted to share with you.[/abstract]
    Today I was in the woods and took some real cool pictures ...
For Twitter and App.net the system will use the defined abstracts.
-For other networks (e.g. when you are using the "statusnet" connector that is used to post to your GNU Social account) the general abstract element will be used.
@@ -574,7 +573,7 @@ While taking pictures in the woods I had a really strange encounter... -The [abstract] element is not working with connectors where we post HTML directly, like Tumblr, Wordpress or Pump.io. +The [abstract] element is not working with connectors where we post HTML directly, like Tumblr, WordPress or Pump.io. For the native connections--that is to e.g. Friendica, Hubzilla, Diaspora or GNU Social--the full posting is used and the contacts instance will display the posting as desired. For postings that are delivered via ActivityPub, the text from the abstract is placed in the summary field. @@ -611,10 +610,10 @@ On Mastodon this field is used for the content warning. Additionally, [pre] blocks preserve spaces:
    -
  • [pre]      Spaces[/pre]
  • +
  • [pre] Spaces[/pre]
-       Spaces + Spaces [nosmile] is used to disable smilies on a post by post basis
diff --git a/doc/Bugs-and-Issues.md b/doc/en/user/bugs-and-issues.md similarity index 91% rename from doc/Bugs-and-Issues.md rename to doc/en/user/bugs-and-issues.md index 126f6af58e..f47e1388cb 100644 --- a/doc/Bugs-and-Issues.md +++ b/doc/en/user/bugs-and-issues.md @@ -1,13 +1,10 @@ -Bugs and Issues -=============== - -* [Home](help) +# Bugs and issues If your server has a support page, you should report any bugs/issues you encounter there first. Reporting to your support page before reporting to the developers makes their job easier, as they don't have to deal with bug reports that might not have anything to do with them. Reducing the workload in this way helps us get new features faster. You can also contact the [friendica support group](https://forum.friendi.ca/profile/helpers) and report your problem there. -Bugs are rarely limited to one person, and the chances are somebody from another node has encountered the problem too, and will be able to help you. +Bugs are rarely limited to one person, and the chances are somebody from another node has encountered the issue too, and will be able to help you. If you're a technical user, or your site doesn't have a support page, you'll need to use the [Bug Tracker](https://github.com/friendica/friendica/issues). This is also used for issues with addons. diff --git a/doc/Channels.md b/doc/en/user/channels.md similarity index 98% rename from doc/Channels.md rename to doc/en/user/channels.md index 63d2582170..f61043d716 100644 --- a/doc/Channels.md +++ b/doc/en/user/channels.md @@ -1,7 +1,4 @@ -Channels -===== - -* [Home](help) +# Channels Channels are a way to discover new content or to display content that you might have missed otherwise. There are several predefined channels, additionally you can create your own channels, based on some rules. @@ -18,8 +15,7 @@ On the contact page you can define the channel frequency for every contact. The * Display only few posts: When a contact creates a lot of posts in a short period, this setting reduces the number of displayed posts in every channel. * Never display posts: Posts from this contact will never be displayed in any channel. -Predefined Channels ---- +## Predefined Channels * For you: Posts from contacts you interact with and who interact with you. In detail, it consists of: * Posts from people you interact with on a more than average level. @@ -38,8 +34,7 @@ Predefined Channels * Audio: Posts with audio. * Videos: Posts with videos. -User defined Channels ---- +## User defined Channels In the "Channels" settings you can create your own channels. @@ -54,8 +49,7 @@ Each channel is defined by these values: * Full Text Search: This can be used to include or exclude content, based on the content and some additional keywords. It uses the "boolean mode" operators from MariaDB: https://mariadb.com/kb/en/full-text-index-overview/#in-boolean-mode * Images, Videos, Audio: When selected, you will see content with the selected media type. This can be combined. If none of these fields are checked, you will see any content, with or without attached media. -Additional keywords for the full text search ---- +## Additional keywords for the full text search Additionally to the search for content, there are keywords that can be used in the full text search. Alternatives are presented with "|". diff --git a/doc/Chats.md b/doc/en/user/chats.md similarity index 83% rename from doc/Chats.md rename to doc/en/user/chats.md index 1fd76ec6f7..c9ad57b4f0 100644 --- a/doc/Chats.md +++ b/doc/en/user/chats.md @@ -1,17 +1,13 @@ -Chats -===== - -* [Home](help) +# Chats There are two possibilities to use chat on your friendica site * IRC Chat * Jappix -IRC-Chat Addon ---- +## IRC-Chat Addon -After activating the addon, you can find the chat at [yoursite.com/irc](../irc). +After activating the addon, you can find the chat at `https://your-site.info/irc`. Note: you can use this chat without any login at your site so that everyone could use it. If you follow the link, you will see the login page of the IRC chat. @@ -25,8 +21,8 @@ The first line shows your name and your current IP address. The right part of the window shows all users. The lower part of the window contains an input field. -Jappix Mini ---- +## Jappix Mini + The Jappix Mini Addon creates a chatbox for jabber- and XMPP-contacts. You should already have a jabber/XMPP-account before setting up the addon. @@ -39,9 +35,11 @@ You can use several servers to create an account: ### 1. Basics -At first you have to get the current version. You can either pull it from [GitHub](https://github.com) like so: - - $> cd /var/www/virtual/YOURSPACE/html/addon; git pull +First you have to get the current version. You can either pull it from [GitHub](https://github.com) like so: +```sh +cd /var/www/virtual/YOURSPACE/html/addon +git pull +``` Or you can download a tar archive here: [jappixmini.tgz](https://github.com/friendica/friendica-addons/blob/stable/jappixmini.tgz) (click at „view raw“). @@ -59,13 +57,13 @@ Activate the BOSH proxy. Go to your user account settings next and choose the addon page. Scroll down until you find the Jappix Mini addon settings. -At first you have to activate the addon. +First you have to activate the addon. Now add your Jabber/XMPP name, the domain/server (without "http"; just "jappix.com"). For „Jabber BOSH Host“ you could use "https://bind.jappix.com/". Note that you need another BOSH server if you do not use jappix.com for your XMPP account. -You can find further information in the „Configuration Help“-section below this fields. -At last you have enter your password (there are some more optional options, you can choose). +You can find further information in the „Configuration Help“-section below these fields. +Finally you enter your password (there are some more optional options, you can choose). Finish these steps with "send" to save the entries. Now, you should find the chatbox at the lower right corner of your browser window. diff --git a/doc/Circles-and-Privacy.md b/doc/en/user/circles-and-privacy.md similarity index 93% rename from doc/Circles-and-Privacy.md rename to doc/en/user/circles-and-privacy.md index abec72f15a..b6ddb41370 100644 --- a/doc/Circles-and-Privacy.md +++ b/doc/en/user/circles-and-privacy.md @@ -1,13 +1,9 @@ -Circles and Privacy -================== - -* [Home](help) - +# Circles and privacy Circles are merely collections of friends. But Friendica uses these to unlock some very powerful features. -**Setting Up Circles** +## Setting Up Circles To create a circle, visit your Friendica "Contacts" page and select "Create a new circle". Give the circle a name. @@ -21,7 +17,7 @@ Below that is another box containing all of your friends who are *not* members o If you click on a photo of a person who isn't in the circle, they will be put into the circle. If you click on a photo of a person who is in the circle, they will be removed from it. -**Access Control** +## Access Control Once you have created a circle, you may use it in any access control list. This is the little lock icon beneath the status update box on your home page. @@ -40,7 +36,7 @@ You will see that since you are only viewing a certain circle of people, your st This is how you keep your future employers from seeing what you write to your drinking buddies. You can override this setting, but this makes it easy to separate your conversations into different friend circles. -**Default Post Privacy** +## Default Post Privacy By default, Friendica assumes that you want all of your posts to be private. Therefore, when you sign up, Friendica creates a circle for you that it will automatically add all of your contacts to. @@ -51,7 +47,7 @@ Note that this behaviour can be overridden by your site admin, in which case you If you want your posts to be "public" by default, you can change your default post permissions on your Settings page. You also have the option to change which circles you post to by default or which circle your new contacts get placed into by default. -**Privacy Concerns To Be Aware Of** +## Privacy Concerns To Be Aware Of These private conversations work best when your friends are Friendica members. We know who else can see the conversations - nobody, *unless* your friends cut and paste the messages and send them to others. @@ -66,20 +62,18 @@ If you look at the Contact Edit page for any person, we will tell you whether or Once you have created a post, you can not change the permissions assigned. Within seconds it has been delivered to lots of people - and perhaps everybody it was addressed to. If you mistakenly created a message and wish to take it back, the best you can do is delete it. -We will send out a delete notification to everybody who received the message - and this should wipe out the message with the same speed as it was initially propagated. +We will send out a deleted notification to everybody who received the message - and this should wipe out the message with the same speed as it was initially propagated. In most cases, it will be completely wiped from the Internet - in under a minute. Again, this applies to Friendica networks. Once a message spreads to other networks, it may not be removed quickly, and in some cases, it may not be removed at all. - -Profiles, Photos, and Privacy -============================= +# Profiles, Photos, and Privacy The decentralised nature of Friendica (many websites exchanging information rather than one website which controls everything) has some implications with privacy as it relates to people on other sites. There are things you should be aware of, so you can decide best how to interact privately. -**Photos** +## Photos Sharing photos privately is a problem. We can only share them __privately__ with Friendica members. @@ -90,7 +84,7 @@ Your friends on other networks will be blocked from viewing these private photos Our developers are working on solutions to allow access to your friends - no matter what network they are on. However we take privacy seriously and don't behave like some networks that __pretend__ your photos are private, but make them available to others without proof of identity. -**Profiles** +## Profiles Your profile and "wall" may also be visited by your friends from other networks, and you can block access to these by web visitors that Friendica doesn't know. Be aware that this could include some of your friends on other networks. diff --git a/doc/Connectors.md b/doc/en/user/connectors.md similarity index 72% rename from doc/Connectors.md rename to doc/en/user/connectors.md index 77d44e909f..4542e94fd3 100644 --- a/doc/Connectors.md +++ b/doc/en/user/connectors.md @@ -1,42 +1,34 @@ -Connectors -========== - -* [Home](help) +# 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. There is also a connector for accessing your email INBOX. -Instructions For Connecting To People On Specific Services -========================================================== +# Instructions For Connecting To People On Specific Services -Friendica ---- +## Friendica You can either connect to others by providing your Identity Address on the 'Connect' page of any Friendica member. -Or you can put their Identity Address into the Connect box on your [Contacts](contacts) page. +Or you can put their Identity Address into the Connect box on your [Contacts](contact) page. -Diaspora ---- +## Diaspora -Add the Diaspora 'handle' to the 'Connect/Follow' text box on your [Contacts](contacts) page. +Add the Diaspora 'handle' to the 'Connect/Follow' text box on your [Contacts](contact) page. -Blogger, Wordpress, RSS feeds, arbitrary web pages ---- +## Blogger, WordPress, RSS feeds, arbitrary web pages -Put the URL into the Connect box on your [Contacts](contacts) page. -PLease note that you will not be able to reply to these contacts. +Put the URL into the Connect box on your [Contacts](contact) page. +PLease note that you will not be able to reply to these contacts. This feed reader feature will allow you to _connect_ with millions of pages on the internet. -All that the pages need to have is a discoverable feed using either the RSS or Atom syndication format, and which provides an author name and a site image in a form which we can extract. +All that the pages need to have is a discoverable feed using either the RSS or Atom syndication format, and which provides an author name and a site image in a form which we can extract. -Email ---- +## Email If the php module for IMAP support is available on your server, Friendica can connect to email contacts as well. Configure the email connector from your [Settings](settings) page. -Once this has been done, you may enter an email address to connect with using the Connect box on your [Contacts](contacts) page. +Once this has been done, you may enter an email address to connect with using the Connect box on your [Contacts](contact) page. They must be the sender of a message which is currently in your INBOX for the connection to succeed. You may include email contacts in private conversations. diff --git a/doc/Remove-Account.md b/doc/en/user/delete-account.md similarity index 95% rename from doc/Remove-Account.md rename to doc/en/user/delete-account.md index 83cb941e80..6e1f0cf044 100644 --- a/doc/Remove-Account.md +++ b/doc/en/user/delete-account.md @@ -1,7 +1,4 @@ -Remove Account -============== - -* [Home](help) +# Deleting an account We don't like to see people leave Friendica, but if you need to remove your account, you should visit the URL diff --git a/doc/events.md b/doc/en/user/events.md similarity index 95% rename from doc/events.md rename to doc/en/user/events.md index 0ec2bc4608..00478b5cff 100644 --- a/doc/events.md +++ b/doc/en/user/events.md @@ -1,7 +1,5 @@ # Events -* [Home](help) - A special form of postings are events. The events you and your contacts share can be found at [/events](/events) on your node. To get there go to your wall and follow the tab "events" @@ -31,14 +29,14 @@ Fields marked with a *** have to be filled. * **Event Finishes**: enter the finishing date/time for the event here When you click in one of these fields a pop-up will be opened that allows you to pick the day and the time. -If you double clicked on the day box in the calendar these fields will be pre-filled for you. +If you double-clicked on the day box in the calendar these fields will be pre-filled for you. The finishing date/time has to be after the beginning date/time of the event. But you don't have to specify it. If the event is open-ended or the finishing date/time does not matter, just select the box below the two first fields. * **Title**: a title for the event * **Description**: a longer description for the event -* **Location**: the location the event will took place +* **Location**: the location the event will take place These three fields describe your events. In the description and location field you can use BBCode to format the text. diff --git a/doc/Export-Import-Contacts.md b/doc/en/user/export-import-contacts.md similarity index 85% rename from doc/Export-Import-Contacts.md rename to doc/en/user/export-import-contacts.md index 824c9e2ebb..7de45c0a6e 100644 --- a/doc/Export-Import-Contacts.md +++ b/doc/en/user/export-import-contacts.md @@ -1,8 +1,6 @@ # Export / Import of followed Contacts -* [Home](help) - -In addition to [move your account](help/Move-Account) you can export and import the list of accounts you follow. +In addition to [move your account](help/user/move-account) you can export and import the list of accounts you follow. The exported list is stored as CSV file that is compatible to the format used by other platforms as e.g. Mastodon, Misskey or Pleroma. ## Export of followed Contacts diff --git a/doc/FAQ.md b/doc/en/user/faq.md similarity index 85% rename from doc/FAQ.md rename to doc/en/user/faq.md index 4e8d9b19eb..cc39c845eb 100644 --- a/doc/FAQ.md +++ b/doc/en/user/faq.md @@ -1,23 +1,6 @@ -Frequently Asked Questions - FAQ -============== +# Frequently asked questions - FAQ -* [Home](help) - -* **[Where I can find help?](help/FAQ#help)** -* **[Why do I get warnings about certificates?](help/FAQ#ssl)** -* **[How can I upload images, files, links, videos and sound files to posts?](help/FAQ#upload)** -* **[Is it possible to have different avatars per profile?](help/FAQ#avatars)** -* **[How can I view Friendica in a certain language?](help/FAQ#language)** -* **[How do blocked, ignored, archived and hidden contacts behave?](help/FAQ#contacts)** -* **[What happens when an account is removed? Is it truly deleted?](help/FAQ#removed)** -* **[Can I subscribe to a hashtag?](help/FAQ#hashtag)** -* **[How to create an RSS feed of the stream?](help/FAQ#rss)** -* **[What friendica clients can I use?](help/FAQ#clients)** - - - - -### Where I can find help? +## Where I can find help? If this FAQ does not answer your question you can always reach out to the community via the following options: @@ -33,8 +16,7 @@ If this FAQ does not answer your question you can always reach out to the commun https://github.com/github/opensource.guide/pull/807 ---> - -### Why do I get warnings about SSL certificates? +## Why do I get warnings about SSL certificates? SSL (Secure Socket Layer) is a technology to encrypt data transfer between computers. Sometimes your browser warns you about a missing or invalid certificate. @@ -44,12 +26,11 @@ These warnings can have three reasons: 2. The server has a self-signed certificate (not recommended). 3. The certificate is expired. -We recommend to talk to the admin(s) of the affected friendica server. (Admins, please see the respective section of the [admin manual](help/SSL).) +We recommend to talk to the admin(s) of the affected friendica server. (Admins, please see the respective section of the [admin manual](help/admin/ssl).) - -### How can I upload images, files, links, videos and sound files to posts? +## How can I upload images, files, links, videos and sound files to posts? -You can upload images from your computer using the [editor](help/Text_editor). +You can upload images from your computer using the [editor](help/user/text-editor). An overview of all uploaded images is listed at *yourpage.com/profile/profilename/photos*. On that page, you can also upload images directly and choose if your contacts will receive a message about this upload. @@ -75,16 +56,14 @@ Therefore, the supported files are dependent on your browser and operating syste Some supported file types are WebM, MP4, MP3 and OGG. See Wikipedia for more of them ([video](http://en.wikipedia.org/wiki/HTML5_video), [audio](http://en.wikipedia.org/wiki/HTML5_audio)). - -### Is it possible to have different avatars per profile? +## Is it possible to have different avatars per profile? Yes. On your Edit/Manage Profiles page, you will find a "change profile photo" link. Clicking this will take you to a page where you can upload a photograph and select which profile it will be associated with. To avoid privacy leakage, we only display the photograph associated with your default profile as the avatar in your posts. - -### How can I view Friendica in a certain language? +## How can I view Friendica in a certain language? You can do this by adding the `lang` parameter to the url in your url bar. The data in the parameter is a [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. @@ -101,12 +80,12 @@ in German: When a certain language is forced, the language remains until session is closed. -### How do blocked, ignored, archived and hidden contacts behave? +## How do blocked, ignored, archived and hidden contacts behave? These are various categories of contacts that are restricted in some way. -Many of these types are related to [Safety](help/Safety). +Many of these types are related to [Safety](help/user/safety). -##### Blocked +### Blocked Direct communication will be blocked. Blocked contacts are not included in delivery, and their own posts to you are not imported. @@ -114,7 +93,7 @@ However, their conversations with your friends will still be visible in your str If you remove a contact completely, they can send you another friend request. Blocked contacts cannot do this. They cannot communicate with you directly, only through friends. -##### Ignored +### Ignored Ignored contacts are included in delivery and will receive your posts and private messages. However, we do not import their posts or private messages to you. @@ -122,18 +101,17 @@ Like blocking, you will still see this person's comments to posts made by your f An addon called "blockem" can be installed to collapse/hide all posts from a particular person in your stream if you desire complete blocking of an individual, including their conversations with your other friends. -##### Archived +### Archived Communication is not possible and will not be attempted. However, unlike blocking, existing posts this person made before being archived will be visible in your stream. -##### Hidden +### Hidden The contact not be displayed in your public friend list. However, a hidden contact will appear normally in conversations and this may expose their hidden status to anybody who can see the conversation. - -### What happens when an account is removed? +## What happens when an account is removed? If you remove your account, it will be scheduled for permanent deletion in *seven days*. As soon as you activate the deletion process you won't be able to log in anymore. @@ -143,19 +121,17 @@ After the elapsed time of seven days, all your posts, messages, photos, and pers Your node will also issue removal requests to all your contacts; this will also remove your profile from the global directory if you are listed. Your username cannot be reissued for future sign-ups for security reasons. - -### Can I follow a hashtag? +## Can I follow a hashtag? Yes. Simply add the hashtag to your saved searches. The posts will appear on your network page. For technical reasons, your answers to such posts won't appear on the "personal" tab in the network page and the whole thread isn't accessible via the API. - -### How to create an RSS feed of the stream? +## How to create an RSS feed of the stream? If you want to share your public page via rss you can use one of the following links: -#### RSS feed of your posts +### RSS feed of your posts basic-url.com//feed/[nickname]/posts @@ -171,15 +147,14 @@ Example: Friendica Support https://forum.friendi.ca/feed/helpers/comments - -### What friendica clients can I use? +## What friendica clients can I use? -Friendica supports [Mastodon API](help/API-Mastodon) and [Twitter API | gnusocial](help/api). +Friendica supports [Mastodon API](help/spec/api/mastodon) and [Twitter API | gnusocial](help/spec/api/index). This means you can use some of the Mastodon and Twitter clients for Friendica. The available features are client specific and may differ. Clients dedicated to Friendica are marked in **bold**. -#### Android +### Android * [AndStatus](http://andstatus.org) ([F-Droid](https://f-droid.org/repository/browse/?fdid=org.andstatus.app), [Google Play](https://play.google.com/store/apps/details?id=org.andstatus.app)) * [Fedilab](https://fedilab.app) ([F-Droid](https://f-droid.org/app/fr.gouv.etalab.mastodon), [Google Play](https://play.google.com/store/apps/details?id=app.fedilab.android)) @@ -195,7 +170,7 @@ Clients dedicated to Friendica are marked in **bold**. * [TwidereX](https://github.com/TwidereProject/TwidereX-Android) ([F-Droid](https://f-droid.org/en/packages/com.twidere.twiderex/), [Google Play](https://play.google.com/store/apps/details?id=com.twidere.twiderex)) * [Yuito](https://github.com/accelforce/Yuito) ([Google Play](https://play.google.com/store/apps/details?id=net.accelf.yuito)) -#### iOS +### iOS * [Mastodon](https://joinmastodon.org/apps) ([App Store](https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974)) * **[Relatica](https://gitlab.com/mysocialportal/relatica)** @@ -203,7 +178,7 @@ Clients dedicated to Friendica are marked in **bold**. * [Tooot](https://github.com/tooot-app) ([App Store](https://apps.apple.com/app/id1549772269)) * [TwidereX](https://github.com/TwidereProject/TwidereX-iOS) ([App Store](https://apps.apple.com/app/twidere-x/id1530314034)) -#### Linux +### Linux * [Choqok](https://choqok.kde.org) * **[Relatica](https://gitlab.com/mysocialportal/relatica)** @@ -211,19 +186,19 @@ Clients dedicated to Friendica are marked in **bold**. * [Toot](https://toot.readthedocs.io/en/latest/) * [Whalebird](https://whalebird.social/en/desktop/contents) ([GitHub](https://github.com/h3poteto/whalebird-desktop)) -#### macOS +### macOS * **[Relatica](https://gitlab.com/mysocialportal/relatica)** * [TheDesk](https://thedesk.top/en/) ([GitHub](https://github.com/cutls/TheDesk)) * [Whalebird](https://whalebird.social/en/desktop/contents) ([App Store](https://apps.apple.com/de/app/whalebird/id1378283354), [GitHub](https://github.com/h3poteto/whalebird-desktop)) -#### Windows +### Windows * **[Relatica](https://gitlab.com/mysocialportal/relatica)** * [TheDesk](https://thedesk.top/en/) ([GitHub](https://github.com/cutls/TheDesk)) * [Whalebird](https://whalebird.social/en/desktop/contents) ([Microsoft Store](https://apps.microsoft.com/detail/9nbw4csdv5hc), [GitHub](https://github.com/h3poteto/whalebird-desktop)) -#### Web Frontend +### Web Frontend * [Halcyon](https://www.halcyon.social/) * [Pinafore](https://github.com/nolanlawson/pinafore) diff --git a/doc/en/user/keyboard-shortcuts.md b/doc/en/user/keyboard-shortcuts.md new file mode 100644 index 0000000000..7f55c1d3d5 --- /dev/null +++ b/doc/en/user/keyboard-shortcuts.md @@ -0,0 +1,6 @@ +# Keyboard shortcuts in Friendica + +## General + +* j: Scroll to next thread +* k: Scroll to previous thread diff --git a/doc/Making-Friends.md b/doc/en/user/making-friends.md similarity index 95% rename from doc/Making-Friends.md rename to doc/en/user/making-friends.md index 85d4044cef..1bccd1c3c2 100644 --- a/doc/Making-Friends.md +++ b/doc/en/user/making-friends.md @@ -1,14 +1,11 @@ -Making Friends -============== - -* [Home](help) +# Making friends Friendship in Friendica can sometimes take on different meaning. But let's keep it simple; you want to be friends with somebody. How do you do it? -The Directories ---- +## The Directories + Friendica has two different kinds of "address book". The directory of the Friendica server you are registered on and a global directory to which your and other Friendica servers submit account information. @@ -23,8 +20,7 @@ If you click through to the global directory, you will be presented with a list You will also see a "Show Community Groups" link, which will direct you to Groups. You connect to people and groups the same way, public groups will automatically accept your introduction, whereas private groups and some individual users will need to manually approve it. -Connect to other Friendica users ---- +## Connect to other Friendica users Visit their profile. Just beneath their profile picture will be the word 'Connect' (we're assuming this is an English language profile). @@ -48,8 +44,8 @@ If you already know somebody's Identity Address, you can enter it in the "connec This will take you through a similar process. -Connect to users of alternate networks ---- +## Connect to users of alternate networks + ### Across the Federation and Fediverse You can also use your Identity Address or other people's Identity Addresses to become friends across the so-called Federation/Fediverse of open source social media. Currently, Friendica supports connections with people on diaspora*, Red, Hubzilla, GNU Social, StatusNet, Mastodon, Pleroma, socialhome, and ganggo platforms. @@ -80,31 +76,29 @@ To subscribe to a mailing list, enter the email in following example format "mai You can "follow" almost anybody or any website that produces a syndication feed (RSS/Atom,etc.). If we can find an information stream and a name to attach to the contact, we'll try to connect with them. -Notification ---- +## Notification + When somebody requests friendship you will receive a notification. You will usually need to approve this before the friendship is complete. -Approval ---- +## Approval + Some networks allow people to send you messages without being friends and without your approval. Friendica does not allow this by default, as it would open a gateway for spam. -Unilateral or bilateral friendships ---- +## Unilateral or bilateral friendships + When you receive a friendship notification from another Friendica member, you will have the option of allowing them as a "Follower" or as a "Friend". If they are a follower, they can see what you have to say, including private communications that you send to them, but not vice versa. As a friend, you can both communicate with each other. diaspora* uses a different terminology, and you are given the option of allowing them to "share with you", or being full friends. -Deleting ---- +## Deleting You can delete a friend no matter what the friendship status - which completely removes everything relating to that person from your website. -Unwanted Behaviour ---- +## Unwanted Behaviour If a contact engages in abuse, harrassment, or other unwanted behaviour, there are various actions you can take. These include: @@ -113,4 +107,4 @@ These include: * Ignoring the contact, so that you will not see their posts * Blocking the contact from receiving your posts -For more information, see [Safety](help/Safety). +For more information, see [Safety](help/user/safety). diff --git a/doc/Move-Account.md b/doc/en/user/move-account.md similarity index 91% rename from doc/Move-Account.md rename to doc/en/user/move-account.md index 9e13d7cad8..b78d5f4e40 100644 --- a/doc/Move-Account.md +++ b/doc/en/user/move-account.md @@ -1,8 +1,4 @@ -How to move your account between servers -============ - -* [Home](help) - +# Moving an account between servers ! **This is an experimental feature** @@ -14,13 +10,12 @@ How to move your account between servers * Load your saved account file and click "Import". * After the move, the account on the old server will not work reliably anymore, and should be not used. +## Friendica contacts -Friendica contacts ---- Friendica will recreate your account on the new server, with your contacts and circles. A message is sent to Friendica contacts, to inform them about your move: If your contacts are running on an updated server, your details on their side will be automatically updated. -Diaspora contacts ---- +## Diaspora contacts + Newer Diaspora servers are able to process "account migration" messages. diff --git a/doc/en/user/quick-start/finally.md b/doc/en/user/quick-start/finally.md new file mode 100644 index 0000000000..8f06415552 --- /dev/null +++ b/doc/en/user/quick-start/finally.md @@ -0,0 +1,12 @@ +And that brings the Quick Start to an end. + +Here are some more things to help get you started: + +**Groups** + +- [Friendica Support](https://forum.friendi.ca/profile/helpers) - problems? This is the place to ask. + +**Documentation** + +- [Connections to other networks](help/user/connectors) +- [Help index](help) diff --git a/doc/Quick-Start-groupsandpages.md b/doc/en/user/quick-start/groups-and-pages.md similarity index 74% rename from doc/Quick-Start-groupsandpages.md rename to doc/en/user/quick-start/groups-and-pages.md index c9a27c6f1c..05ba28653b 100644 --- a/doc/Quick-Start-groupsandpages.md +++ b/doc/en/user/quick-start/groups-and-pages.md @@ -1,5 +1,5 @@ This is the global directory. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can [click this link](help/user/quick-start/groups-and-pages) to bring yourself back here. On this page, you'll find a collection of groups. Groups are not real people. @@ -13,8 +13,6 @@ Simply find a group you're interested in, and connect to it the same way you did There are a lot of groups, and you're likely to get lost. Remember the link at the top of this page will bring you back here. -Once you've added some groups, move on to the next section. - - - +Once you've added some groups, [move on to the next section](help/user/quick-start/finally). + diff --git a/doc/Quick-Start-guide.md b/doc/en/user/quick-start/guide.md similarity index 91% rename from doc/Quick-Start-guide.md rename to doc/en/user/quick-start/guide.md index ebcc6243f2..a357d3d862 100644 --- a/doc/Quick-Start-guide.md +++ b/doc/en/user/quick-start/guide.md @@ -18,8 +18,6 @@ Once you've finished writing your post, click on the padlock icon or permissions If you do not change anything, your post will be public. This means it will appear to anybody who views your profile, and in the community tab if your site has it enabled, as well as in the network tab of any of your contacts. -Play around with this a bit, then when you're ready to move on, we'll take a look at the Network Tab - - - +Play around with this a bit, then when you're ready to move on, we'll take a look at the [Network Tab](help/user/quick-start/network). + diff --git a/doc/Quick-Start-makingnewfriends.md b/doc/en/user/quick-start/making-new-friends.md similarity index 72% rename from doc/Quick-Start-makingnewfriends.md rename to doc/en/user/quick-start/making-new-friends.md index d642905698..d1f9b961a8 100644 --- a/doc/Quick-Start-makingnewfriends.md +++ b/doc/en/user/quick-start/making-new-friends.md @@ -1,5 +1,5 @@ This is your Suggested Friends page. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can [click this link](help/user/quick-start/making-new-friends) to bring yourself back here. This is a bit like the Friend Suggestions page of Facebook. Everybody on this list has agreed that they may be suggested as a friend. @@ -14,8 +14,6 @@ Now you've added one, you're probably lost. Click the link at the top of this page to go back to the suggested friends list and add some more. Feel uncomfortable adding people you don't know? -Don't worry - that's where Groups and Pages come in! - - - +Don't worry - that's where [Groups and Pages](help/user/quick-start/groups-and-pages) come in! + diff --git a/doc/Quick-Start-network.md b/doc/en/user/quick-start/network.md similarity index 62% rename from doc/Quick-Start-network.md rename to doc/en/user/quick-start/network.md index e0c138d2bd..bcabfcbaff 100644 --- a/doc/Quick-Start-network.md +++ b/doc/en/user/quick-start/network.md @@ -1,5 +1,5 @@ This is your Network Tab. -If you get lost, you can click this link to bring yourself back here. +If you get lost, you can [click this link](help/user/quick-start/network) to bring yourself back here. This is a bit like the Newsfeed at Facebook or the Stream at Diaspora. It's where all the posts from your contacts, groups, and feeds will appear. @@ -7,8 +7,6 @@ If you're new, you won't see anything in this page, unless you posted your statu If you've already added a few friends, you'll be able to see their posts. Here, you can comment, like, or dislike posts, or click on somebody's name to visit their profile page where you can write on their wall. -Now we need to fill it up, the first step, is to make some new friends. - - - +Now we need to fill it up, the first step, is to [make some new friends](help/user/quick-start/making-new-friends). + diff --git a/doc/Safety.md b/doc/en/user/safety.md similarity index 97% rename from doc/Safety.md rename to doc/en/user/safety.md index 4ecd927e87..9a8e6c7bcc 100644 --- a/doc/Safety.md +++ b/doc/en/user/safety.md @@ -1,15 +1,11 @@ -Safety -====== - -* [Home](help) +# Safety Each Friendica instance is linked together with a global network of other servers, some running Friendica and some running other software. These servers support a diverse global community of millions of users. Inevitably, some of these users are malicious. Friendica provides several features to keep you safe from abuse and harrassment. -Terms of Service ---- +## Terms of Service Each instance is entitled to define its own Terms of Service, also often called a Code of Conduct. These terms include rules for behaviour. @@ -21,8 +17,7 @@ Remember that conversations frequently involve participants from different insta Participants are only bound by the rules of the server where they have an account, not by the rules of your server. Terms of Service may even be completely incompatible. -Reporting ---- +## Reporting Your local administrators are responsible for ensuring a safe online environment for all users on your server. They rely on reports from users to highlight behaviour that puts other users at risk. @@ -32,8 +27,7 @@ You will be given an opportunity to select the type of problem you are seeing. Your local administrator then has the option of blocking that user for all users on your local instance. If a remote server is a constant source of abuse and their administrators are unable or unwilling to control their users behaviour, your administrator can even block the entire remote server. -Ignoring ---- +## Ignoring Once you have become friends, if you find the person constantly sends you spam or worthless information, you can "Ignore" them - without breaking off the friendship or even alerting them to the fact that you aren't interested in anything they are saying. In many ways they are like a "follower" - but they don't know this. @@ -45,8 +39,7 @@ Some servers are frequent sources of abusive or other unwanted behaviour. For this reason you can also choose to ignore entire servers. Users on that server can still follow you as normal. -Blocking ---- +## Blocking You can also "block" a person. This completely blocks communications with that person. @@ -66,8 +59,7 @@ In some cases this could lead to retaliation. There are several other ways someone can determine that you have blocked them, and see your public posts despite the block. For example, they can simply log out and view your posts. -Archiving ---- +## Archiving Archiving is similar to blocking. However, existing posts this person made before being archived will be visible in your stream. diff --git a/doc/Tags-and-Mentions.md b/doc/en/user/tags-and-mentions.md similarity index 95% rename from doc/Tags-and-Mentions.md rename to doc/en/user/tags-and-mentions.md index 8424b026cb..086950d88c 100644 --- a/doc/Tags-and-Mentions.md +++ b/doc/en/user/tags-and-mentions.md @@ -1,13 +1,8 @@ -Tags and Mentions -================= - - -* [Home](help) - +# Tags and mentions Like many other modern social networks, Friendica uses a special notation inside messages to indicate "tags" or contextual links to other entities. -**Mentions** +## Mentions People are tagged by preceding their name with the @ character. @@ -39,9 +34,9 @@ If you select a group from the ACL a !-mention will be added automatically to yo If you sort your contacts into circles, you cannot @-mention these circles. But you can select the circle in the access control when creating a new posting, to allow (or disallow) a certain circle of people to see the posting. -See [Circles and Privacy](help/Circles-and-Privacy) for more details about grouping your contacts. +See [Circles and privacy](help/user/circles-and-privacy) for more details about grouping your contacts. -**Topical Tags** +## Topical tags Topical tags are indicated by preceding the tag name with the # character. This will create a link in the post to a generalised site search for the term provided. diff --git a/doc/en/user/text-comment.md b/doc/en/user/text-comment.md new file mode 100644 index 0000000000..46e49a1efa --- /dev/null +++ b/doc/en/user/text-comment.md @@ -0,0 +1,29 @@ +# Comment, sort and delete posts + +Here you can find an overview of the different ways to comment and sort existing posts. Attention: we've used the "diabook" theme. If you're using another theme, some of the icons may be different. + +diabook + +The different icons + +post_thumbs_up.png This symbol is used to indicate that you like the post. Click it twice to undo your choice.

+ +post_thumbs_down.png This symbol is used to indicate that you dislike the post. Click it twice to undo your choice. +

+ +post_share.png This symbol is used to share a post. A copy of this post will automatically appear in your status editor and add a link to the original post. +

+ +post_mark.png This symbol is used to mark a post. Marked posts will appear on your network page at the "starred" tab (from "star"). Click it twice to undo your choice. +

+ +post_tag.png This symbol is used to tag a post with a self-chosen keyword. When you click at the word, you'll get a list of all posts with this tag. Attention: you can't delete the tag once you've set one. +

+ +post_categorize.png This symbol is used to categorize posts. Choose an existing folder or create a new one. You'll find the created folder on your network page under the "saved folders" tab. +

+ +post_delete.png This symbol is used to delete your own post or to remove a post of another person from your stream. +

+ +post_choose.png This symbol is used to choose more than one post to delete in a single step. After selecting all posts, go to the end of the page and click "Delete Selected Items".

diff --git a/doc/Text_editor.md b/doc/en/user/text-editor.md similarity index 51% rename from doc/Text_editor.md rename to doc/en/user/text-editor.md index c20b9ac649..25b40a1295 100644 --- a/doc/Text_editor.md +++ b/doc/en/user/text-editor.md @@ -4,10 +4,7 @@ figure img { padding: 2px; } figure figcaption { background: #eeeeee; color: #444444; padding: 2px; font-style: italic;} -Creating posts -=========== - -* [Home](help) +# Creating posts Here you can find an overview of the different ways to create and edit your post. @@ -15,12 +12,12 @@ One click on the Pencil & Paper icon in the top right of your Home or Network pa Below are examples of the post editor in 3 of Friendica's common themes:
-frio editor +frio editor
Post editor, with the Frio (popular default) theme.

-vier editor +vier editor
Post editor, with the Vier theme.

@@ -33,29 +30,29 @@ The Big Empty Textarea is where you write your new post. You can simply enter your text there and click the "Share" button, and your new post will be public on your profile page and shared to your contact. If plain text is not so exciting to you, Friendica understands BBCode to spice up your posts: bold, italic, images, links, lists.. -See [BBCode tags reference](help/BBCode) page to see all what you can do. +See [BBCode tags reference](help/user/bbcode) page to see all what you can do. The icons under the text area are there to help you to write posts quickly, but vary depending on the theme: With the Frio theme, the Underline, Italics and Bold buttons should be self-explanatory. -editor Upload a picture from your computer. The image will be uploaded and correct bbcode tag will be added to your post.* In the Frio theme, use the Browser tab instead to Upload and/or attach content to your post. +editor Upload a picture from your computer. The image will be uploaded and correct bbcode tag will be added to your post.* In the Frio theme, use the Browser tab instead to Upload and/or attach content to your post.

-paper_clip This depends on the theme: For Frio, this is to attach remote content - put in a URL to embed in your post, including video or audio content. For other themes: Add files from your computer. Same as picture, but for generic attachment to the post.* +paper_clip This depends on the theme: For Frio, this is to attach remote content - put in a URL to embed in your post, including video or audio content. For other themes: Add files from your computer. Same as picture, but for generic attachment to the post.*

-chain Add a web address (url). Enter a URL and Friendica will add to your post a link to the url and an excerpt from the web site, if possible. +chain Add a web address (url). Enter a URL and Friendica will add to your post a link to the url and an excerpt from the web site, if possible.

-video Add a video. Enter the url to a video (ogg) or to a video page on youtube or vimeo, and it will be embedded in your post with a preview. (In the Frio theme, this is done with the paperclip as mentioned above.) Friendica is using [HTML5](http://en.wikipedia.org/wiki/HTML5_video) for embedding content. Therefore, the supported files are depending on your browser and operating system (OS). Some filetypes are WebM, MP4 and OGG.* +video Add a video. Enter the url to a video (ogg) or to a video page on youtube or vimeo, and it will be embedded in your post with a preview. (In the Frio theme, this is done with the paperclip as mentioned above.) Friendica is using [HTML5](http://en.wikipedia.org/wiki/HTML5_video) for embedding content. Therefore, the supported files are depending on your browser and operating system (OS). Some filetypes are WebM, MP4 and OGG.*

-mic Add an audio. Same as video, but for audio. Depending on your browser and operation system MP3, OGG and AAC are supported. Additionally, you are able to add URLs from audiohosters like Soundcloud. +mic Add an audio. Same as video, but for audio. Depending on your browser and operation system MP3, OGG and AAC are supported. Additionally, you are able to add URLs from audiohosters like Soundcloud.

-globe Or location Set your geographic location. This location will be added into a Google Maps search. That's why a note like "New York" or "10004" is already enough. +globe Or location Set your geographic location. This location will be added into a Google Maps search. That's why a note like "New York" or "10004" is already enough.


@@ -66,21 +63,21 @@ These icons can change depending on the theme. Some examples: - +
Vier: vier.pngvier.png  
-* how to [upload](help/FAQ#upload) files +* how to [upload](help/user/faq#upload) files

 

-**lock icon The Lock / Permissions** +**lock icon The Lock / Permissions** In Frio, the Permissions tab, or in other themes, the Lock button, is the most important feature in Friendica. If the lock is open, your post will be public, and will show up on your profile page when strangers visit it. Click on it and the *Permission settings* window (aka "*Access Control Selector*" or "*ACL Selector*") pops up. There you can select who can see the post.
-Permission settings window +Permission settings window
Permission settings window with some contact selected
@@ -95,4 +92,4 @@ Click again on "show" or "don't show" to switch it off. You can search for contacts or circles with the search box. -See also [Circles and Privacy](help/Circles-and-Privacy) +See also [Circles and privacy](help/user/circles-and-privacy) diff --git a/doc/themes.md b/doc/en/user/themes.md similarity index 97% rename from doc/themes.md rename to doc/en/user/themes.md index 5804868836..512421b138 100644 --- a/doc/themes.md +++ b/doc/en/user/themes.md @@ -1,7 +1,5 @@ # Themes -* [Home](help) - The default Theme in Friendica is called [frio](https://github.com/friendica/friendica/tree/stable/view/theme/frio). Open `Settings > Display > Custom Theme Settings` adjust the Theme to your liking. Select your preferred Appearance - light, dark or black - and your favorite Accent color. Click `Submit` to save your changes. diff --git a/doc/Two-Factor-Authentication.md b/doc/en/user/two-factor-authentication.md similarity index 99% rename from doc/Two-Factor-Authentication.md rename to doc/en/user/two-factor-authentication.md index b413f9f253..8f152fa0f4 100644 --- a/doc/Two-Factor-Authentication.md +++ b/doc/en/user/two-factor-authentication.md @@ -1,7 +1,5 @@ # Configuring two-factor authentication -* [Home](help) - You can configure two-factor authentication using a mobile app. A time-based one-time password (TOTP) application automatically generates an authentication code that changes after a certain period of time. @@ -17,7 +15,7 @@ Nonetheless, we recommend: - For iOS, [Matt Rubin's MIT-licensed Authenticator app](https://mattrubin.me/authenticator). - For Android, [andOTP](https://github.com/andOTP/andOTP). - + ### 2. Record your one-use recovery codes From your [two-factor authentication user settings](/settings/2fa), enter your password and click on "Enable two-factor authentication". diff --git a/doc/install-ejabberd.md b/doc/install-ejabberd.md deleted file mode 100644 index dbdc0b975d..0000000000 --- a/doc/install-ejabberd.md +++ /dev/null @@ -1,45 +0,0 @@ -Install an ejabberd with synchronized credentials -================================================= - -* [Home](help) - -[Ejabberd](https://www.ejabberd.im/) is a chat server that uses XMPP as messaging protocol that you can use with a large amount of clients. -In conjunction with the "xmpp" addon it can be used for a web based chat solution for your users. - -Installation ------------- - -- Change it's owner to whichever user is running the server, ie. ejabberd - - $ chown ejabberd:ejabberd /path/to/friendica/bin/auth_ejabberd.php - -- Change the access mode so it is readable only to the user ejabberd and has exec - - $ chmod 700 /path/to/friendica/bin/auth_ejabberd.php - -- Edit your ejabberd.cfg file, comment out your auth_method and add: - - {auth_method, external}. - {extauth_program, "/path/to/friendica/bin/auth_ejabberd.php"}. - -- Disable the module "mod_register" and disable the registration: - - {access, register, [{deny, all}]}. - -- Enable BOSH: - - Enable the module "mod_http_bind" - - Edit this line: - - {5280, ejabberd_http, [captcha, http_poll, http_bind]} - - - In your apache configuration for your site add this line: - - ProxyPass /http-bind http://127.0.0.1:5280/http-bind retry=0 - -- Restart your ejabberd service, you should be able to login with your friendica credentials - -Other hints ------------ -- if a user has a space or a @ in the nickname, the user has to replace these characters: - - " " (space) is replaced with "%20" - - "@" is replaced with "(a)" diff --git a/doc/README.md b/doc/readme.md similarity index 53% rename from doc/README.md rename to doc/readme.md index 4902b4cdf6..3c98d0132c 100644 --- a/doc/README.md +++ b/doc/readme.md @@ -1,21 +1,27 @@ # About the docs of the Friendica Project -**Note**: It is expected that some of the links in these files wont work in the Friendica repository as they are supposed to work on an installed Friendica node. +**Note**: It is expected that some of the links in these files won't work in the Friendica repository as they are supposed to work on an installed Friendica node. ## User and Admin documentation Every Friendica node has the _current_ version of the user and admin documentation available in the `/help` location. + The documentation is mainly done in English, but the pages can be translated and some are already to German. -If you want to help expanding the documentation or the translation, please register an account at the [Friendica wiki](https://wiki.friendi.ca) where the [texts are maintained](https://wiki.friendi.ca/docs). -The documentation is periodically merged back from there to the _development_ branch of Friendica. + +We greatly appreciate help in keeping Friendica well documented, with information that's up to date, so contributions are very welcome. +The documentation lives in the core Friendica repository which, for now, [still lives on GitHub](https://github.com/friendica/friendica/). + +To contribute currently, you will need to make an account on GitHub, and if you're a developer or otherwise technically savvy you can create a `pull request` with your suggested changes +You can make your changes using GitHub's builtin text editors, or locally. +Alternatively you can create an `issue` with your suggested changes, and someone else can make a `pull request` based on your suggestions. Images that you use in the documentation should be located in the `img` sub-directory of this directory. Translations are located in sub-directories named after the language codes, e.g. `de`. Depending on the selected interface language the different translations will be applied, or the `en` original will be used as a fall-back. -## Developers Documentation +## Developer documentation We provide a configuration file for [Doxygen](https://www.doxygen.nl/index.html) in the root of the Friendica repository. With that you should be able to extract some documentation from the source code. -In addition there are some documentation files about the database structure in `doc`db`. +In addition there are some documentation files about the database structure under the `database` subdirectory. diff --git a/mod/photos.php b/mod/photos.php index af334ed562..5d295a2ca9 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -656,7 +656,7 @@ function photos_content() $default_upload_box = Renderer::replaceMacros(Renderer::getMarkupTemplate('photos_default_uploader_box.tpl'), []); $default_upload_submit = Renderer::replaceMacros(Renderer::getMarkupTemplate('photos_default_uploader_submit.tpl'), [ - '$submit' => DI::l10n()->t('Submit'), + '$submit' => DI::l10n()->t('Upload selected picture'), ]); // Get the relevant size limits for uploads. Abbreviated var names: MaxImageSize -> mis; upload_max_filesize -> umf @@ -772,12 +772,11 @@ function photos_content() $album_e = $album; $o .= Renderer::replaceMacros($edit_tpl, [ - '$nametext' => DI::l10n()->t('New album name: '), - '$nickname' => $user['nickname'], - '$album' => $album_e, - '$hexalbum' => bin2hex($album), - '$submit' => DI::l10n()->t('Submit'), - '$dropsubmit' => DI::l10n()->t('Delete Album') + '$nametext' => DI::l10n()->t('New album name: '), + '$nickname' => $user['nickname'], + '$album' => $album_e, + '$hexalbum' => bin2hex($album), + '$submit' => DI::l10n()->t('Save changes'), ]); } } elseif ($can_post) { @@ -1022,7 +1021,7 @@ function photos_content() ]; } } - $tags = ['title' => DI::l10n()->t('Tags: '), 'tags' => $tag_arr]; + $tags = ['title' => DI::l10n()->t('Tags'), 'tags' => $tag_arr]; if ($cmd === 'edit' && !empty($tag_arr)) { $tags['removeanyurl'] = 'post/' . $link_item['id'] . '/tag/remove?return=' . urlencode(DI::args()->getCommand()); $tags['removetitle'] = DI::l10n()->t('[Select tags to remove]'); @@ -1042,7 +1041,7 @@ function photos_content() '$id' => $ph[0]['id'], '$album' => ['albname', DI::l10n()->t('New album name'), $album_e, ''], '$caption' => ['desc', DI::l10n()->t('Caption'), $caption_e, ''], - '$tags' => ['newtag', DI::l10n()->t('Add a Tag'), "", DI::l10n()->t('Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping')], + '$tags' => ['newtag', DI::l10n()->t('Add a Tag'), "", "", "", "", "", DI::l10n()->t('Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping')], '$rotate_none' => ['rotate', DI::l10n()->t('Do not rotate'), 0, '', true], '$rotate_cw' => ['rotate', DI::l10n()->t("Rotate CW \x28right\x29"), 1, ''], '$rotate_ccw' => ['rotate', DI::l10n()->t("Rotate CCW \x28left\x29"), 2, ''], @@ -1053,7 +1052,7 @@ function photos_content() '$aclselect' => $aclselect_e, '$item_id' => $link_item['id'] ?? 0, - '$submit' => DI::l10n()->t('Submit'), + '$submit' => DI::l10n()->t('Save changes'), '$delete' => DI::l10n()->t('Delete Photo'), // ACL permissions box @@ -1095,7 +1094,7 @@ function photos_content() '$mytitle' => DI::l10n()->t('This is you'), '$myphoto' => $contact['thumb'], '$comment' => DI::l10n()->t('Comment'), - '$submit' => DI::l10n()->t('Submit'), + '$submit' => DI::l10n()->t('Comment'), '$preview' => DI::l10n()->t('Preview'), '$loading' => DI::l10n()->t('Loading...'), '$qcomment' => $qcomment, @@ -1151,7 +1150,7 @@ function photos_content() '$mytitle' => DI::l10n()->t('This is you'), '$myphoto' => $contact['thumb'], '$comment' => DI::l10n()->t('Comment'), - '$submit' => DI::l10n()->t('Submit'), + '$submit' => DI::l10n()->t('Comment'), '$preview' => DI::l10n()->t('Preview'), '$qcomment' => $qcomment, '$rand_num' => Crypto::randomDigits(12), @@ -1231,7 +1230,7 @@ function photos_content() '$mytitle' => DI::l10n()->t('This is you'), '$myphoto' => $contact['thumb'], '$comment' => DI::l10n()->t('Comment'), - '$submit' => DI::l10n()->t('Submit'), + '$submit' => DI::l10n()->t('Comment'), '$preview' => DI::l10n()->t('Preview'), '$qcomment' => $qcomment, '$rand_num' => Crypto::randomDigits(12), diff --git a/mods/release-list-include.txt b/mods/release-list-include.txt index a7cdac7b35..3f200929f0 100644 --- a/mods/release-list-include.txt +++ b/mods/release-list-include.txt @@ -13,7 +13,6 @@ doc/ images/ mod/ mods/ -spec/ src/ static/ vendor/ diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index c8cff6c777..bd68272381 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -323,16 +323,18 @@ class Conversation $tpl = Renderer::getMarkupTemplate('jot-header.tpl'); $this->page['htmlhead'] .= Renderer::replaceMacros($tpl, [ - '$newpost' => 'true', - '$geotag' => $geotag, - '$nickname' => $x['nickname'], - '$ispublic' => $this->l10n->t('Visible to everybody'), - '$linkurl' => $this->l10n->t('Please enter a image/video/audio/webpage URL:'), - '$term' => $this->l10n->t('Tag term:'), - '$fileas' => $this->l10n->t('Save to Folder'), - '$whereareu' => $this->l10n->t('Where are you right now?'), - '$delitems' => $this->l10n->t("Delete item\x28s\x29?"), - '$is_mobile' => $this->mode->isMobile(), + '$newpost' => 'true', + '$geotag' => $geotag, + '$nickname' => $x['nickname'], + '$ispublic' => $this->l10n->t('Visible to everybody'), + '$linkurl' => $this->l10n->t('Please enter a image/video/audio/webpage URL:'), + '$term' => $this->l10n->t('Tag term:'), + '$fileas' => $this->l10n->t('Save to Folder'), + '$whereareu' => $this->l10n->t('Where are you right now?'), + '$delitems' => $this->l10n->t("Delete item\x28s\x29?"), + '$postPublished' => $this->l10n->t('Post published.'), + '$goToPost' => $this->l10n->t('Go to post'), + '$is_mobile' => $this->mode->isMobile(), ]); $jotplugins = $this->eventDispatcher->dispatch( diff --git a/src/Content/Feature.php b/src/Content/Feature.php index 641340133c..27a39978a7 100644 --- a/src/Content/Feature.php +++ b/src/Content/Feature.php @@ -12,24 +12,25 @@ use Friendica\Event\ArrayFilterEvent; class Feature { - const ACCOUNTS = 'accounts'; const ADD_ABSTRACT = 'add_abstract'; - const ARCHIVE = 'archive'; const CATEGORIES = 'categories'; - const CHANNELS = 'channels'; - const CIRCLES = 'circles'; const COMMUNITY = 'community'; const EXPLICIT_MENTIONS = 'explicit_mentions'; - const FOLDERS = 'folders'; - const GROUPS = 'forumlist_profile'; const MEMBER_SINCE = 'profile_membersince'; - const NETWORKS = 'networks'; - const NOSHARER = 'nosharer'; const PHOTO_LOCATION = 'photo_location'; const PUBLIC_CALENDAR = 'public_calendar'; - const SEARCHES = 'searches'; const TAGCLOUD = 'tagadelic'; - const TRENDING_TAGS = 'trending_tags'; + // The different widgets: + const ACCOUNTS = 'accounts'; + const ARCHIVE = 'archive'; + const CIRCLES = 'circles'; + const CHANNELS = 'channels'; + const FOLDERS = 'folders'; + const GROUPS = 'forumlist_profile'; + const NETWORKS = 'networks'; + const NOSHARER = 'nosharer'; + const SEARCHES = 'searches'; + const TRENDING_TAGS = 'trending_tags'; /** * check if feature is enabled diff --git a/src/Content/Item.php b/src/Content/Item.php index 6d116561ca..826146f68d 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -373,13 +373,17 @@ class Item public function photoMenu(array $item, string $formSecurityToken): string { $this->profiler->startRecording('rendering'); - $sub_link = $contact_url = $pm_url = $status_link = ''; + $sub_link = $contact_url = $pm_url = $status_link = $complete_url = ''; $photos_link = $posts_link = $block_link = $ignore_link = $collapse_link = $ignoreserver_link = ''; if ($this->userSession->getLocalUserId() && $this->userSession->getLocalUserId() == $item['uid'] && $item['gravity'] == ItemModel::GRAVITY_PARENT && !$item['self'] && !$item['mention']) { $sub_link = 'javascript:doFollowThread(' . $item['id'] . '); return false;'; } + if ($this->userSession->getLocalUserId() && $this->userSession->getLocalUserId() === $item['uid'] && $item['network'] === Protocol::ACTIVITYPUB && $item['gravity'] === ItemModel::GRAVITY_PARENT && !$item['self']) { + $complete_url = 'javascript:doCompleteThread(' . $item['uri-id'] . '); return false;'; + } + $author = [ 'uid' => 0, 'id' => $item['author-id'], @@ -396,14 +400,12 @@ class Item $cid = 0; $pcid = $item['author-id']; - $network = ''; $rel = 0; $condition = ['uid' => $this->userSession->getLocalUserId(), 'uri-id' => $item['author-uri-id']]; - $contact = DBA::selectFirst('contact', ['id', 'network', 'rel'], $condition); + $contact = DBA::selectFirst('contact', ['id', 'network', 'rel', 'contact-type', 'protocol', 'self'], $condition); if (DBA::isResult($contact)) { - $cid = $contact['id']; - $network = $contact['network']; - $rel = $contact['rel']; + $cid = $contact['id']; + $rel = $contact['rel']; } if (!empty($pcid)) { @@ -423,7 +425,7 @@ class Item $contact_url = 'contact/' . $cid; $posts_link = $contact_url . '/posts'; - if (in_array($network, [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA])) { + if (Contact::canReceivePrivateMessages($contact)) { $pm_url = 'message/new/' . $cid; } } @@ -431,6 +433,7 @@ class Item if ($this->userSession->getLocalUserId()) { $menu = [ $this->l10n->t('Follow Thread') => $sub_link, + $this->l10n->t('Complete Thread') => $complete_url, $this->l10n->t('View Status') => $status_link, $this->l10n->t('View Profile') => $profile_link, $this->l10n->t('View Photos') => $photos_link, diff --git a/src/Content/Nav.php b/src/Content/Nav.php index 4ca3564c6c..fbf42059d2 100644 --- a/src/Content/Nav.php +++ b/src/Content/Nav.php @@ -308,9 +308,9 @@ class Nav // Don't show notifications for public communities if ($this->session->get('page_flags', '') != User::PAGE_FLAGS_COMMUNITY) { $nav['introductions'] = ['notifications/intros', $this->l10n->t('Introductions'), '', $this->l10n->t('Friend Requests')]; - $nav['notifications'] = ['notifications', $this->l10n->t('Notifications'), '', $this->l10n->t('Notifications')]; - $nav['notifications']['all'] = ['notifications/system', $this->l10n->t('See all notifications'), '', '']; - $nav['notifications']['mark'] = ['', $this->l10n->t('Mark as seen'), '', $this->l10n->t('Mark all system notifications as seen')]; + $nav['notifications'] = ['notifications', $this->l10n->t('Notifications'), '', $this->l10n->t('Notifications')]; + $nav['notifications']['all'] = ['notifications/system?show=all', $this->l10n->t('View all'), '', '']; + $nav['notifications']['mark'] = ['', $this->l10n->t('Mark as read'), '', $this->l10n->t('Mark all system notifications as seen')]; } $nav['messages'] = ['message', $this->l10n->t('Messages'), '', $this->l10n->t('Private mail')]; diff --git a/src/Content/Post/Entity/PostMedia.php b/src/Content/Post/Entity/PostMedia.php index 1d4b9c09e2..a9e1f2b7c6 100644 --- a/src/Content/Post/Entity/PostMedia.php +++ b/src/Content/Post/Entity/PostMedia.php @@ -42,6 +42,8 @@ use Psr\Http\Message\UriInterface; * @property-read ?string $embedHtml * @property-read ?int $embedWidth * @property-read ?int $embedHeight + * @property-read ?string $pageType + * @property-read ?array $schemaTypes * @property-read ?int $attachId * @property-read ?string $language * @property-read ?string $published @@ -131,6 +133,10 @@ class PostMedia extends BaseEntity protected $embedWidth; /** @var ?int In pixels */ protected $embedHeight; + /** @var ?string */ + protected $pageType; + /** @var ?array */ + protected $schemaTypes; public function __construct( int $uriId, @@ -164,7 +170,9 @@ class PostMedia extends BaseEntity ?string $embedType = null, ?string $embedHtml = null, ?int $embedWidth = null, - ?int $embedHeight = null + ?int $embedHeight = null, + ?string $pageType = null, + ?array $schemaTypes = null ) { $this->uriId = $uriId; $this->url = $url; @@ -198,8 +206,120 @@ class PostMedia extends BaseEntity $this->embedHtml = $embedHtml; $this->embedWidth = $embedWidth; $this->embedHeight = $embedHeight; + $this->pageType = $pageType; + $this->schemaTypes = $schemaTypes; } + /** + * Checks if the media has a player url set + * + * @return boolean + */ + public function hasPlayerUrl(): bool + { + return !is_null($this->playerUrl) && $this->playerUrl !== ''; + } + + /** + * Checks if the media has a player width set + * + * @return boolean + */ + public function hasPlayerWidth(): bool + { + return !is_null($this->playerWidth) && $this->playerWidth > 0; + } + + /** + * Checks if the media has a player height set + * + * @return boolean + */ + public function hasPlayerHeight(): bool + { + return !is_null($this->playerHeight) && $this->playerHeight > 0; + } + + /** + * Checks if the media has an embed html set + * + * @return boolean + */ + public function hasEmbedHtml(): bool + { + return !is_null($this->embedHtml) && $this->embedHtml !== ''; + } + + /** + * Checks if the media has an embed width set + * + * @return boolean + */ + public function hasEmbedWidth(): bool + { + return !is_null($this->embedWidth) && $this->embedWidth > 0; + } + + /** + * Checks if the media has an embed height set + * + * @return boolean + */ + public function hasEmbedHeight(): bool + { + return !is_null($this->embedHeight) && $this->embedHeight > 0; + } + + /** + * Checks if the media is a photo + * + * @return boolean + */ + public function isPhoto(): bool + { + return $this->embedType === 'photo'; + } + + /** + * Checks if the media is a video + * + * @return boolean + */ + public function isVideo(): bool + { + return $this->embedType === 'video' || $this->getPageType() === 'video'; + } + + /** + * Checks if the media is an article + * + * @return boolean + */ + public function isArticle(): bool + { + if (is_array($this->schemaTypes)) { + foreach (['Article', 'BackgroundNewsArticle', 'NewsArticle'] as $type) { + if (in_array($type, $this->schemaTypes)) { + return true; + } + } + } + + return in_array($this->getPageType(), ['article']); + } + + /** + * Get the page type. In case of a type with main und sub category (separated by `.`), only the main category is returned + * + * @return string|null + */ + public function getPageType(): ?string + { + if (is_null($this->pageType)) { + return null; + } + return explode('.', $this->pageType)[0]; + } /** * Get media link for given media id @@ -313,7 +433,9 @@ class PostMedia extends BaseEntity $this->embedType, $this->embedHtml, $this->embedWidth, - $this->embedHeight + $this->embedHeight, + $this->pageType, + $this->schemaTypes ); } @@ -351,7 +473,9 @@ class PostMedia extends BaseEntity $this->embedType, $this->embedHtml, $this->embedWidth, - $this->embedHeight + $this->embedHeight, + $this->pageType, + $this->schemaTypes ); } diff --git a/src/Content/Post/Factory/PostMedia.php b/src/Content/Post/Factory/PostMedia.php index af45a5c8a3..5bba3140f5 100644 --- a/src/Content/Post/Factory/PostMedia.php +++ b/src/Content/Post/Factory/PostMedia.php @@ -68,7 +68,9 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow $row['embed-type'], $row['embed-html'], $row['embed-width'], - $row['embed-height'] + $row['embed-height'], + $row['page-type'], + $row['schematypes'] ? json_decode($row['schematypes'], true) : null ); } @@ -141,6 +143,8 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow 'embed-html' => $attachment['embed_html'] ?? null, 'embed-width' => $attachment['embed_width'] ?? null, 'embed-height' => $attachment['embed_height'] ?? null, + 'page-type' => $attachment['page_type'] ?? null, + 'schematypes' => null, 'attach-id' => null, 'language' => null, 'published' => null, @@ -190,10 +194,12 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow 'embed-html' => $data['embed']['html'] ?? null, 'embed-width' => $data['embed']['width'] ?? null, 'embed-height' => $data['embed']['height'] ?? null, + 'page-type' => $data['pagetype'] ?? null, 'attach-id' => null, 'language' => $data['language'] ?? null, 'published' => $data['published'] ?? null, 'modified' => $data['modified'] ?? null, + 'schematypes' => isset($data['schematypes']) ? json_encode($data['schematypes']) : null, ]; return $this->createFromTableRow($row); diff --git a/src/Content/Post/Repository/PostMedia.php b/src/Content/Post/Repository/PostMedia.php index eae63e11b6..080bc74927 100644 --- a/src/Content/Post/Repository/PostMedia.php +++ b/src/Content/Post/Repository/PostMedia.php @@ -27,6 +27,14 @@ use Friendica\Util\Proxy; use Friendica\Util\Strings; use Psr\Log\LoggerInterface; +/** + * Repository for PostMedia entities. + * + * Provides persistence and rendering helpers for post media objects + * (images, audio, video, embeds, etc.). + * + * @package Friendica\Content\Post\Repository + */ class PostMedia extends BaseRepository { protected static $table_name = 'post-media'; @@ -42,6 +50,17 @@ class PostMedia extends BaseRepository /** @var Item */ private $item; + /** + * PostMedia repository constructor. + * + * @param Database $database Database connection wrapper + * @param LoggerInterface $logger PSR-3 logger + * @param PostMediaFactory $factory Factory for creating entities + * @param IManagePersonalConfigValues $pConfig Personal configuration access + * @param IManageConfigValues $config Global configuration access + * @param BaseURL $baseURL Base URL helper + * @param Item $item Item helper + */ public function __construct(Database $database, LoggerInterface $logger, PostMediaFactory $factory, IManagePersonalConfigValues $pConfig, IManageConfigValues $config, BaseURL $baseURL, Item $item) { parent::__construct($database, $logger, $factory); @@ -52,6 +71,16 @@ class PostMedia extends BaseRepository $this->item = $item; } + /** + * Low level select helper used by higher-level selectors. + * + * Queries the `post-media` table and maps rows to entities. Invalid rows + * are logged and skipped. + * + * @param array $condition DBA-style condition array + * @param array $params Optional positional parameters + * @return PostMediasCollection Collection of PostMediaEntity objects + */ protected function _select(array $condition, array $params = []): PostMediasCollection { $rows = $this->db->selectToArray(static::$table_name, [], $condition, $params); @@ -69,10 +98,10 @@ class PostMedia extends BaseRepository } /** - * Returns a single PostMedia entity, selected by their id. + * Return a single PostMedia entity selected by its id. * - * @param int $postMediaId - * @return PostMediaEntity + * @param int $postMediaId Primary key of the media row + * @return PostMediaEntity The entity for the requested id * @throws NotFoundException */ public function selectById(int $postMediaId): PostMediaEntity @@ -83,11 +112,11 @@ class PostMedia extends BaseRepository } /** - * Select PostMedia collection for the given uri-id and the given types + * Select PostMedia collection for the given uri-id and optional types. * - * @param integer $uriId - * @param array $types - * @return PostMediasCollection + * @param int $uriId URI id to select media for + * @param array $types Optional list of media types to restrict the result + * @return PostMediasCollection Collection of PostMedia entities */ public function selectByUriId(int $uriId, array $types = []): PostMediasCollection { @@ -101,12 +130,12 @@ class PostMedia extends BaseRepository } /** - * Select PostMedia entity for the given uri-id, the media url and the given types + * Select a single PostMedia entity for the given uri-id and media URL. * - * @param integer $uriId - * @param string $url - * @param array $types - * @return PostMediaEntity + * @param int $uriId URI id to search within + * @param string $url Full media URL to match + * @param array $types Optional list of media types to restrict the search + * @return PostMediaEntity|null Matching media entity or null when not found */ public function selectByURL(int $uriId, string $url, array $types = []): ?PostMediaEntity { @@ -120,6 +149,16 @@ class PostMedia extends BaseRepository return $medias[0] ?? null; } + /** + * Map a PostMedia entity to an array of storage fields. + * + * The returned array is suitable for insert/update operations on the + * `post-media` table. When $includeId is true the `id` field is included. + * + * @param PostMediaEntity $PostMedia Entity to map + * @param bool $includeId Include the `id` field when true + * @return array Associative array of storage fields + */ public function getFields(PostMediaEntity $PostMedia, bool $includeId = false): array { $fields = [ @@ -150,6 +189,8 @@ class PostMedia extends BaseRepository 'embed-html' => $PostMedia->embedHtml, 'embed-height' => $PostMedia->embedHeight, 'embed-width' => $PostMedia->embedWidth, + 'page-type' => $PostMedia->pageType, + 'schematypes' => $PostMedia->schemaTypes ? json_encode($PostMedia->schemaTypes) : null, 'attach-id' => $PostMedia->attachId, 'language' => $PostMedia->language, 'published' => $PostMedia->published, @@ -162,6 +203,15 @@ class PostMedia extends BaseRepository return $fields; } + /** + * Save a PostMedia entity to the database. + * + * Updates when an id is present, otherwise inserts and returns the + * persisted entity. + * + * @param PostMediaEntity $PostMedia Entity to persist + * @return PostMediaEntity Persisted entity + */ public function save(PostMediaEntity $PostMedia): PostMediaEntity { $fields = $this->getFields($PostMedia); @@ -181,19 +231,21 @@ class PostMedia extends BaseRepository /** - * Split the attachment media in the three segments "visual", "link" and "additional" + * Split the attachment media into four segments: `visual`, `link`, `additional`, 'hidden'. * - * @param int $uri_id URI id - * @param array $links list of links that shouldn't be added - * @param bool $has_media - * @return PostMediasCollection[] Three collections in "visual", "link" and "additional" keys + * @param int $uri_id URI id the attachments belong to + * @param array $links List of link URLs that should be ignored + * @param bool $has_media Whether the item has media at all + * @param bool $local_visitor Whether the viewer is local (affects remote-media handling) + * @return PostMediasCollection[] Associative array with keys `visual`, `link`, `additional`, 'hidden' */ - public function splitAttachments(int $uri_id, array $links = [], bool $has_media = true): array + public function splitAttachments(int $uri_id, array $links = [], bool $has_media = true, bool $local_visitor = true): array { $attachments = [ 'visual' => new PostMediasCollection(), 'link' => new PostMediasCollection(), 'additional' => new PostMediasCollection(), + 'hidden' => new PostMediasCollection(), ]; if (!$has_media) { @@ -214,6 +266,7 @@ class PostMedia extends BaseRepository // Check if there is any HLS media // This is used to determine if we should suppress some of the media types + /** @var PostMediaEntity $PostMedia */ foreach ($PostMedias as $PostMedia) { if ($PostMedia->type == PostMediaEntity::TYPE_HLS) { $is_hls = true; @@ -223,6 +276,7 @@ class PostMedia extends BaseRepository } } + /** @var PostMediaEntity $PostMedia */ foreach ($PostMedias as $PostMedia) { foreach ($links as $link) { if (Strings::compareLink($link, $PostMedia->url)) { @@ -253,15 +307,14 @@ class PostMedia extends BaseRepository $previews[] = $PostMedia->preview; } - //$PostMedia->filetype = $filetype; - //$PostMedia->subtype = $subtype; - if ($PostMedia->type == PostMediaEntity::TYPE_HTML) { $attachments['link'][] = $PostMedia; continue; } - if (in_array($PostMedia->type, [PostMediaEntity::TYPE_AUDIO, PostMediaEntity::TYPE_IMAGE, PostMediaEntity::TYPE_HLS])) { + if (!$local_visitor && !$this->displayMedia($PostMedia)) { + $attachments['hidden'][] = $PostMedia; + } elseif (in_array($PostMedia->type, [PostMediaEntity::TYPE_AUDIO, PostMediaEntity::TYPE_IMAGE, PostMediaEntity::TYPE_HLS])) { $attachments['visual'][] = $PostMedia; } elseif ($PostMedia->type == PostMediaEntity::TYPE_VIDEO) { if ($is_torrent) { @@ -297,6 +350,31 @@ class PostMedia extends BaseRepository return $attachments; } + /** + * Decide whether a media item should be displayed based on configuration. + * + * @param PostMediaEntity $PostMedia Media entity to check + * @return bool display mode + */ + private function displayMedia(PostMediaEntity $PostMedia): bool + { + if (!in_array($PostMedia->type, [PostMediaEntity::TYPE_AUDIO, PostMediaEntity::TYPE_IMAGE, PostMediaEntity::TYPE_HLS, PostMediaEntity::TYPE_VIDEO])) { + return true; + } + + if ($this->baseURL->isLocalUri($PostMedia->url)) { + return $this->config->get('system', 'display_local_media'); + } else { + return $this->config->get('system', 'display_remote_media'); + } + } + + /** + * Create a PostMedia entity from a remote URL using siteinfo parsing. + * + * @param string $url Remote resource URL + * @return PostMediaEntity Created media entity + */ public function createFromUrl(string $url): PostMediaEntity { $data = ParseUrl::getSiteinfoCached($url); @@ -304,6 +382,12 @@ class PostMedia extends BaseRepository return $this->fetchAdditionalData($media); } + /** + * Fetch additional metadata for a PostMedia and return an updated entity. + * + * @param PostMediaEntity $postMedia Media entity to enrich + * @return PostMediaEntity Enriched media entity + */ public function fetchAdditionalData(PostMediaEntity $postMedia): PostMediaEntity { $data = $this->getFields($postMedia, true); @@ -312,14 +396,15 @@ class PostMedia extends BaseRepository } /** - * Embed remote media, that had been added with the [embed] element + * Replace `[embed]` link placeholders in the provided HTML with embed markup. * - * @param string $html The already rendered HTML output - * @param integer $uid The user the output is rendered for - * @param integer $uri_id The uri-id of the item that is rendered - * @return string + * @param string $html HTML that may contain anchor tags with class `embed` + * @param int $uid Viewer user id used for personal preferences + * @param int $uri_id URI id of the item being rendered + * @param bool $local_visitor Whether the viewer is local + * @return string Modified HTML with embeds replaced */ - public function addEmbed(string $html, int $uid, int $uri_id): string + public function addEmbed(string $html, int $uid, int $uri_id, bool $local_visitor = true): string { if ($html == '') { return $html; @@ -363,14 +448,16 @@ class PostMedia extends BaseRepository } } - if ($media->type === Post\Media::AUDIO) { + if (!$local_visitor && !$this->displayMedia($media)) { + $player = ''; + } elseif ($media->type === Post\Media::AUDIO) { $player = $this->getAudioAttachment($media); } elseif (in_array($media->type, [Post\Media::VIDEO, Post\Media::HLS])) { $player = $this->getVideoAttachment($media, $uid); - } elseif ($allow_embed && !empty($media->playerUrl)) { + } elseif ($allow_embed && $media->hasPlayerUrl() && $media->hasPlayerHeight()) { $player = $this->getPlayerIframe($media); - } elseif ($allow_embed && !empty($media->embedHtml)) { - $player = '' . $this->getEmbedIframe($media) . ''; + } elseif ($allow_embed && $media->hasEmbedHtml() && !$media->isPhoto()) { + $player = $this->getEmbedIframe($media); } else { $player = $this->getLinkAttachment($media); } @@ -392,6 +479,13 @@ class PostMedia extends BaseRepository return $html; } + /** + * Render a video attachment as HTML. + * + * @param PostMediaEntity $postMedia Media entity to render + * @param int $uid Viewer user id + * @return string HTML snippet for the video attachment + */ public function getVideoAttachment(PostMediaEntity $postMedia, int $uid): string { if ($postMedia->preview || ($postMedia->blurhash && $this->config->get('system', 'ffmpeg_installed'))) { @@ -400,29 +494,29 @@ class PostMedia extends BaseRepository $preview_url = ''; } - if (($postMedia->height ?? 0) > ($postMedia->width ?? 0)) { - $height = min($this->config->get('system', 'max_height') ?: '100%', $postMedia->height); - $width = 'auto'; - } else { - $height = 'auto'; - $width = '100%'; - } - - if ($this->pConfig->get($uid, 'system', 'embed_media', false) && ($postMedia->playerUrl != '') && ($postMedia->playerHeight > 0)) { + if ($this->pConfig->get($uid, 'system', 'embed_media', false) && $postMedia->hasPlayerUrl() && $postMedia->hasPlayerHeight()) { $media = $this->getPlayerIframe($postMedia); - } elseif ($this->pConfig->get($uid, 'system', 'embed_media', false) && ($postMedia->embedHtml != '')) { + } elseif ($this->pConfig->get($uid, 'system', 'embed_media', false) && $postMedia->hasEmbedHtml() && !$postMedia->isPhoto()) { $media = $this->getEmbedIframe($postMedia); } else { - /// @todo Move the template to /content as well - $media = Renderer::replaceMacros(Renderer::getMarkupTemplate($postMedia->type == Post\Media::HLS ? 'hls_top.tpl' : 'video_top.tpl'), [ + if ($postMedia->width === 0 && $postMedia->height === 0) { + return $this->getAudioAttachment($postMedia); + } + if ($this->config->get('system', 'videojs')) { + $template = 'content/videojs.tpl'; + } else { + $template = $postMedia->type == Post\Media::HLS ? 'content/hls.tpl' : 'content/video.tpl'; + } + $media = Renderer::replaceMacros(Renderer::getMarkupTemplate($template), [ '$video' => [ 'id' => $postMedia->id, 'src' => (string)$postMedia->url, 'name' => $postMedia->name ?: $postMedia->url, 'preview' => $preview_url, 'mime' => (string)$postMedia->mimetype, - 'height' => $height, - 'width' => $width, + 'height' => 'auto', + 'width' => '100%', + 'style' => 'aspect-ratio:' . $postMedia->width . '/' . $postMedia->height . ';', 'description' => $postMedia->description, ], ]); @@ -430,46 +524,99 @@ class PostMedia extends BaseRepository return $media; } + /** + * Build an iframe-based player markup for the given media. + * + * @param PostMediaEntity $postMedia Media entity providing player URL and dimensions + * @return string HTML markup for the iframe player + */ public function getPlayerIframe(PostMediaEntity $postMedia): string { if ($postMedia->playerUrl == '') { return ''; } - $div_style = ''; $iframe_style = ''; - $height = min($this->config->get('system', 'max_height'), $postMedia->playerHeight); + $height = '100%'; + $width = '100%'; - if ($postMedia->playerWidth != 0 && $postMedia->playerHeight != 0 && $postMedia->playerWidth > $this->config->get('system', 'max_width') && $postMedia->playerWidth > $postMedia->playerHeight) { - $factor = round($postMedia->playerHeight / $postMedia->playerWidth, 2) * 100; - $height = '100%'; - $iframe_style .= 'position:absolute;left:0px;top:0px;'; - $div_style .= 'position:relative;padding-bottom:' . $factor . '%;'; + if ($postMedia->isVideo()) { + if ($postMedia->hasPlayerWidth() && $postMedia->hasPlayerHeight()) { + $iframe_style .= 'aspect-ratio:' . $postMedia->playerWidth . '/' . $postMedia->playerHeight . ';'; + if ($postMedia->playerWidth < $postMedia->playerHeight) { + $height = $postMedia->playerHeight; + $width = ''; + } else { + $height = ''; + } + } + } else { + if ($postMedia->hasPlayerHeight()) { + $height = $postMedia->playerHeight . 'px'; + } + if ($postMedia->hasPlayerWidth()) { + $width = $postMedia->playerWidth . 'px'; + } } return Renderer::replaceMacros(Renderer::getMarkupTemplate('content/iframe.tpl'), [ 'src' => $postMedia->playerUrl, 'height' => $height, - 'width' => $postMedia->embedWidth && $postMedia->embedWidth <= $this->config->get('system', 'max_width') ? $postMedia->embedWidth : '100%', - 'div_style' => $div_style, + 'width' => $width, 'iframe_style' => $iframe_style, ]); } + /** + * Build an iframe wrapper for embed HTML provided by the media. + * + * @param PostMediaEntity $postMedia Media entity containing embed HTML and dimensions + * @return string Rendered iframe embedding the media + */ public function getEmbedIframe(PostMediaEntity $postMedia): string { if ($postMedia->embedHtml == '') { return ''; } + $iframe_style = ''; + $height = '100%'; + $width = '100%'; + + if ($postMedia->isVideo()) { + if ($postMedia->hasEmbedWidth() && $postMedia->hasEmbedHeight()) { + $iframe_style .= 'aspect-ratio:' . $postMedia->embedWidth . '/' . $postMedia->embedHeight . ';'; + if ($postMedia->embedWidth < $postMedia->embedHeight) { + $height = $postMedia->embedHeight; + $width = ''; + } else { + $height = ''; + } + } + } else { + if ($postMedia->hasEmbedHeight()) { + $height = $postMedia->embedHeight . 'px'; + } + if ($postMedia->hasEmbedWidth()) { + $width = $postMedia->embedWidth . 'px'; + } + } + return Renderer::replaceMacros(Renderer::getMarkupTemplate($postMedia->embedHeight ? 'content/embed-iframe.tpl' : 'content/embed-iframe-resize.tpl'), [ - 'id' => 'iframe-' . hash('md5', $postMedia->embedHtml), - 'src' => $postMedia->embedHtml, - 'height' => $postMedia->embedHeight + 20, - 'width' => $postMedia->embedWidth && $postMedia->embedWidth <= $this->config->get('system', 'max_width') ? $postMedia->embedWidth : '100%', + 'id' => 'iframe-' . hash('md5', $postMedia->embedHtml), + 'src' => $postMedia->embedHtml, + 'height' => $height, + 'width' => $width, + 'iframe_style' => $iframe_style, ]); } + /** + * Render an audio attachment as HTML. + * + * @param PostMediaEntity $postMedia Media entity to render + * @return string HTML snippet for the audio player + */ public function getAudioAttachment(PostMediaEntity $postMedia): string { return Renderer::replaceMacros(Renderer::getMarkupTemplate('content/audio.tpl'), [ @@ -482,6 +629,12 @@ class PostMedia extends BaseRepository ]); } + /** + * Render a generic link attachment. + * + * @param PostMediaEntity $postMedia Media entity to render + * @return string HTML snippet for the link attachment + */ public function getLinkAttachment(PostMediaEntity $postMedia): string { return Renderer::replaceMacros(Renderer::getMarkupTemplate('content/link.tpl'), [ diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index ef4cf32e56..874ca6de1f 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -58,6 +58,7 @@ class BBCode const PREVIEW_NO_IMAGE = 1; const PREVIEW_LARGE = 2; const PREVIEW_SMALL = 3; + const PREVIEW_AUTO = 4; /** * Fetches attachment data that were generated with the "attachment" element @@ -412,7 +413,7 @@ class BBCode * @return string * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function convertAttachment(string $text, int $simplehtml = self::INTERNAL, array $data = [], int $uriid = 0, int $preview_mode = self::PREVIEW_LARGE, bool $embed = false): string + public static function convertAttachment(string $text, int $simplehtml = self::INTERNAL, array $data = [], int $uriid = 0, int $preview_mode = self::PREVIEW_AUTO, bool $embed = false): string { DI::profiler()->startRecording('rendering'); $data = $data ?: self::getAttachmentData($text); @@ -443,19 +444,26 @@ class BBCode $return = sprintf('
', $data['type']); } - if ($embed && (($data['player_url'] != '' && $data['player_height'] != 0) || $data['embed_html'] != '')) { + if ($embed) { $media = DI::postMediaFactory()->createFromAttachment($data, $uriid); - if ($data['player_url'] != '' && $data['player_height'] != 0) { - $return .= DI::postMediaRepository()->getPlayerIframe($media); + if ($media->hasPlayerUrl() && $media->hasPlayerHeight()) { + $embed_media = DI::postMediaRepository()->getPlayerIframe($media); + } elseif ($media->hasEmbedHtml() && !$media->isPhoto()) { + $embed_media = DI::postMediaRepository()->getEmbedIframe($media); } else { - $return .= DI::postMediaRepository()->getEmbedIframe($media); + $embed_media = null; + } + + if ($embed_media) { + $return .= $embed_media; + + $preview_mode = self::PREVIEW_NO_IMAGE; + unset($data['title']); + unset($data['url']); + unset($data['description']); + unset($data['provider_url']); + unset($data['provider_name']); } - $preview_mode = self::PREVIEW_NO_IMAGE; - unset($data['title']); - unset($data['url']); - unset($data['description']); - unset($data['provider_url']); - unset($data['provider_name']); } if ($preview_mode == self::PREVIEW_NO_IMAGE) { @@ -464,7 +472,7 @@ class BBCode } if (!empty($data['title']) && !empty($data['url'])) { - $preview_class = $preview_mode == self::PREVIEW_LARGE ? 'attachment-image' : 'attachment-preview'; + $preview_class = in_array($preview_mode, [self::PREVIEW_AUTO, self::PREVIEW_LARGE]) ? 'attachment-image' : 'attachment-preview'; if (!empty($data['image']) && empty($data['text']) && ($data['type'] == 'photo')) { $return .= sprintf('', $data['url'], self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title']); } else { diff --git a/src/Content/Text/HTML.php b/src/Content/Text/HTML.php index c8afc8ce28..3d789e7fa0 100644 --- a/src/Content/Text/HTML.php +++ b/src/Content/Text/HTML.php @@ -1067,4 +1067,38 @@ class HTML { return ($text != html_entity_decode($text)) || ($text != strip_tags($text)); } + + /** + * Remove HTML elements with a specific class name + * + * @param string $html + * @param string $className + * @return string the HTML without the removed HTML element + */ + public static function removeElementByClass(string $html, string $className): string + { + $dom = new DOMDocument(); + libxml_use_internal_errors(true); + + $dom->loadHTML(mb_convert_encoding('' . $html . '', 'HTML-ENTITIES', "UTF-8"), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + libxml_clear_errors(); + + $xpath = new DOMXPath($dom); + + $nodes = $xpath->query("//*[contains(@class, '" . $className . "')]"); + if (!$nodes || $nodes->length == 0) { + return $html; + } + + foreach ($nodes as $node) { + $node->parentNode->removeChild($node); + } + + $html = trim($dom->saveHTML()); + if (substr($html, 0, 6) == '' && substr($html, -7) == '') { + $html = substr($html, 6, -7); + } + + return $html; + } } diff --git a/src/Content/Widget.php b/src/Content/Widget.php index c983a51f59..6adb8c24b7 100644 --- a/src/Content/Widget.php +++ b/src/Content/Widget.php @@ -608,6 +608,19 @@ class Widget } } + $widget_timelineorder = json_decode(DI::pConfig()->get($uid, 'system', 'widget_timeline_order')); + if (!empty($widget_timelineorder)) { + $tmp = []; + foreach($widget_timelineorder as $order) { + foreach($channels as $channel) { + if($channel['ref'] == $order) { + $tmp[] = $channel; + } + } + } + $channels = $tmp; + } + return self::filter( 'channel', DI::l10n()->t('Channels'), diff --git a/src/Core/Console.php b/src/Core/Console.php index 5dec5be257..ac639fe199 100644 --- a/src/Core/Console.php +++ b/src/Core/Console.php @@ -41,36 +41,42 @@ class Console extends \Asika\SimpleConsole\Console Usage: bin/console [--version] [-h|--help|-?] [] [-v] Commands: - addon Addon management - cache Manage node cache - clearavatarcache Clear the file based avatar cache - config Edit site config - contact Contact management - createdoxygen Generate Doxygen headers daemon Interact with the Friendica daemon + help Show help about a command, e.g (bin/console help config) jetstream Interact with the Jetstream daemon worker Start worker process - dbstructure Do database updates - docbloxerrorchecker Check the file tree for DocBlox errors - extract Generate translation string file for the Friendica project (deprecated) - globalcommunityblock Block remote profile from interacting with this node - globalcommunitysilence Silence a profile from the global community page - archivecontact Archive a contact when you know that it isn't existing anymore - help Show help about a command, e.g (bin/console help config) - autoinstall Starts automatic installation of friendica based on values from htconfig.php - lock Edit site locks - maintenance Set maintenance mode for this node - movetoavatarcache Move cached avatars to the file based avatar cache - mergecontacts Merge duplicated contact entries - user User management - php2po Generate a messages.po file from a strings.php file - po2php Generate a strings.php file from a messages.po file - typo Checks for parse errors in Friendica files - postupdate Execute pending post update scripts (can last days) - relocate Update node base URL - serverblock Manage blocked servers - storage Manage storage backend - relay Manage ActivityPub relay servers + + node management + archivecontact Archive a contact when you know that it isn't existing anymore + cache Manage node cache + contact Contact management + globalcommunityblock Block remote profile from interacting with this node + globalcommunitysilence Silence a profile from the global community page + lock Edit site locks + mergecontacts Merge duplicated contact entries + serverblock Manage blocked servers + relay Manage ActivityPub relay servers + user User management + + node configuration + addon Addon management + autoinstall Starts automatic installation of friendica based on values from htconfig.php + clearavatarcache Clear the file based avatar cache + config Edit site config + dbstructure Do database updates + maintenance Set maintenance mode for this node + movetoavatarcache Move cached avatars to the file based avatar cache + postupdate Execute pending post update scripts (can last days) + relocate Update node base URL + storage Manage storage backend + + developer + createdoxygen Generate Doxygen headers + docbloxerrorchecker Check the file tree for DocBlox errors + extract Generate translation string file for the Friendica project (deprecated) + php2po Generate a messages.po file from a strings.php file + po2php Generate a strings.php file from a messages.po file + typo Checks for parse errors in Friendica files Options: -h|--help|-? Show help information diff --git a/src/Core/Logger/Util/Introspection.php b/src/Core/Logger/Util/Introspection.php index 0856a59e9c..925031851b 100644 --- a/src/Core/Logger/Util/Introspection.php +++ b/src/Core/Logger/Util/Introspection.php @@ -73,7 +73,7 @@ class Introspection implements IHaveCallIntrospections 'line' => $trace[$i - 1]['line'] ?? null, 'function' => $trace[$i]['function'] ?? null, 'request-id' => $this->requestId, - 'stack' => System::callstack(15, 0, true, ['Friendica\Core\Logger\Type\StreamLogger', 'Friendica\Core\Logger\Type\AbstractLogger', 'Friendica\Core\Logger\Type\WorkerLogger', 'Friendica\Core\Logger']), + 'stack' => System::callstack(15, 1, ['Friendica\Core\Logger\Type\StreamLogger', 'Friendica\Core\Logger\Type\AbstractLogger', 'Friendica\Core\Logger\Type\WorkerLogger', 'Friendica\Core\Logger']), ]; } diff --git a/src/Core/System.php b/src/Core/System.php index d7367e871c..dc6d0a068f 100644 --- a/src/Core/System.php +++ b/src/Core/System.php @@ -212,25 +212,54 @@ class System $this->logger->info('Executed "proc_open"', ['command' => $cmdline]); } + /** + * Get the callstack without the database operations + * + * @return array the callstack + */ + public static function getCallstack(): array + { + $backtrace = []; + $file = ''; + $line = 0; + foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $trace) { + if (!isset($trace['file']) || !isset($trace['function']) || !isset($trace['line'])) { + continue; + } + if (in_array(basename($trace['file']), ['DBA.php', 'Database.php'])) { + continue; + } + if (in_array(basename($trace['function']), ['selectView', 'selectPosts', 'selectFirstPost', 'fetch', 'toArray', 'exists', 'count', 'selectFirst', 'selectToArray', 'select', 'selectFirstForUser', 'selectForUser'])) { + continue; + } + if ($line != 0) { + $new = $trace; + $new['file'] = $file; + $new['line'] = $line; + $backtrace[] = $new; + } + $file = $trace['file']; + $line = $trace['line']; + } + + return $backtrace; + } + /** * Returns a string with a callstack. Can be used for logging. * * @param integer $depth How many calls to include in the stacks after filtering * @param int $offset How many calls to shave off the top of the stack, for example if * this is called from a centralized method that isn't relevant to the callstack - * @param bool $full If enabled, the callstack is not compacted * @param array $exclude * @return string */ - public static function callstack(int $depth = 4, int $offset = 0, bool $full = false, array $exclude = []): string + public static function callstack(int $depth = 4, int $offset = 0, array $exclude = []): string { - $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - - // We remove at least the first two items from the list since they contain data that we don't need. - $trace = array_slice($trace, 2 + $offset); + // We remove at least the first item from the list since they contain data that we don't need. + $trace = array_slice(self::getCallstack(), 1 + $offset); $callstack = []; - $previous = ['class' => '', 'function' => '', 'database' => false]; // The ignore list contains all functions that are only wrapper functions $ignore = ['call_user_func_array']; @@ -240,25 +269,12 @@ class System if (in_array($func['class'], $exclude)) { continue; } - - if (!$full && in_array($previous['function'], ['insert', 'fetch', 'toArray', 'exists', 'count', 'selectFirst', 'selectToArray', - 'select', 'update', 'delete', 'selectFirstForUser', 'selectForUser']) - && (substr($previous['class'], 0, 15) === 'Friendica\Model')) { - continue; - } - - // Don't show multiple calls from the Database classes to show the essential parts of the callstack - $func['database'] = in_array($func['class'], ['Friendica\Database\DBA', 'Friendica\Database\Database']); - if ($full || !$previous['database'] || !$func['database']) { - $classparts = explode("\\", $func['class']); - $callstack[] = array_pop($classparts).'::'.$func['function'] . (isset($func['line']) ? ' (' . $func['line'] . ')' : ''); - $previous = $func; - } + $classparts = explode("\\", $func['class']); + $callstack[] = array_pop($classparts).'::'.$func['function'] . (isset($func['line']) ? ' (' . $func['line'] . ')' : ''); } elseif (!in_array($func['function'], $ignore)) { $func['database'] = ($func['function'] == 'q'); $callstack[] = $func['function'] . (isset($func['line']) ? ' (' . $func['line'] . ')' : ''); $func['class'] = ''; - $previous = $func; } } diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 6a5ac37b9a..1574cadbf5 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -1493,4 +1493,14 @@ class Worker return $execute; } + + /** + * Check if we are in worker mode + * + * @return boolean + */ + public static function isInWorkerMode(): bool + { + return (DI::logger() instanceof WorkerLogger); + } } diff --git a/src/Database/Database.php b/src/Database/Database.php index c037a3198b..82522a100a 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -723,13 +723,13 @@ class Database if (($duration > $this->config->get('system', 'db_loglimit'))) { $duration = round($duration, 3); - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + $backtrace = System::getCallstack(); @file_put_contents( $this->config->get('system', 'db_log'), DateTimeFormat::utcNow() . "\t" . $duration . "\t" . - basename($backtrace[1]['file']) . "\t" . - $backtrace[1]['line'] . "\t" . $backtrace[2]['function'] . "\t" . + basename($backtrace[0]['file']) . "\t" . + $backtrace[0]['line'] . "\t" . $backtrace[0]['function'] . "\t" . substr($this->replaceParameters($sql, $args), 0, 4000) . "\n", FILE_APPEND ); diff --git a/src/Model/APContact.php b/src/Model/APContact.php index 8ecc3ed8af..eb8a3bef8d 100644 --- a/src/Model/APContact.php +++ b/src/Model/APContact.php @@ -68,7 +68,7 @@ class APContact if (!empty($link['template']) && ($link['rel'] == ActivityNamespace::OSTATUSSUB)) { $data['subscribe'] = $link['template']; - } elseif (!empty($link['href']) && !empty($link['type']) && ($link['rel'] == 'self') && ($link['type'] == 'application/activity+json')) { + } elseif (!empty($link['href']) && !empty($link['type']) && ($link['rel'] == 'self') && in_array($link['type'], ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'])) { $data['url'] = $link['href']; } elseif (!empty($link['href']) && !empty($link['type']) && ($link['rel'] == ActivityNamespace::WEBFINGERPROFILE) && ($link['type'] == 'text/html')) { $data['alias'] = $link['href']; @@ -260,9 +260,21 @@ class APContact if (is_array($apcontact['photo']) || !empty($compacted['as:icon']['as:url']['@id'])) { $apcontact['photo'] = JsonLD::fetchElement($compacted['as:icon'], 'as:url', '@id'); } elseif (empty($apcontact['photo'])) { - $photo = JsonLD::fetchElementArray($compacted, 'as:icon', 'as:url'); - if (!empty($photo[0]['@id'])) { - $apcontact['photo'] = $photo[0]['@id']; + $prevwidth = 0; + $prevheight = 0; + $photo = JsonLD::fetchElementArray($compacted, 'as:icon', 'as:url'); + $heights = JsonLD::fetchElementArray($compacted, 'as:icon', 'as:height'); + $widths = JsonLD::fetchElementArray($compacted, 'as:icon', 'as:width'); + if (is_array($photo) && is_array($heights) && is_array($widths)) { + foreach ($photo as $key => $url) { + $height = $heights[$key]['@value'] ?? 0; + $width = $widths[$key]['@value'] ?? 0; + if (($width >= $prevwidth) || ($height >= $prevheight)) { + $apcontact['photo'] = $url['@id']; + } + $prevwidth = $width; + $prevheight = $height; + } } } diff --git a/src/Model/Contact.php b/src/Model/Contact.php index b2f9e2bd63..a5afd3c21d 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -251,7 +251,7 @@ class Contact Contact\User::insertForContactArray($contact); if ((empty($contact['baseurl']) || empty($contact['gsid'])) && Probe::isProbable($contact['network'])) { - DI::logger()->debug('Update missing baseurl', ['id' => $contact['id'], 'url' => $contact['url'], 'callstack' => System::callstack(4, 0, true)]); + DI::logger()->debug('Update missing baseurl', ['id' => $contact['id'], 'url' => $contact['url'], 'callstack' => System::callstack(4, 0)]); UpdateContact::add(['priority' => Worker::PRIORITY_MEDIUM, 'dont_fork' => true], $contact['id']); } @@ -1367,7 +1367,7 @@ class Contact * @throws InternalServerErrorException * @throws \ImagickException */ - public static function getIdForURL(string $url = null, int $uid = 0, $update = null, array $default = []): int + public static function getIdForURL(?string $url = null, int $uid = 0, $update = null, array $default = []): int { $contact_id = 0; @@ -1629,7 +1629,7 @@ class Contact * @return string posts in HTML * @throws Exception */ - public static function getPostsFromUrl(string $contact_url, int $uid, bool $only_media = false, string $last_created = null): string + public static function getPostsFromUrl(string $contact_url, int $uid, bool $only_media = false, ?string $last_created = null): string { return self::getPostsFromId(self::getIdForURL($contact_url), $uid, $only_media, $last_created); } @@ -1644,7 +1644,7 @@ class Contact * @return string posts in HTML * @throws Exception */ - public static function getPostsFromId(int $cid, int $uid, bool $only_media = false, string $last_created = null): string + public static function getPostsFromId(int $cid, int $uid, bool $only_media = false, ?string $last_created = null): string { $contact = DBA::selectFirst('contact', ['contact-type', 'network', 'name', 'nick'], ['id' => $cid]); if (!DBA::isResult($contact)) { @@ -1671,7 +1671,7 @@ class Contact if ($only_media) { $condition = DBA::mergeConditions($condition, [ - "`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", + "`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?, ?))", Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO, Post\Media::HLS ]); } @@ -1834,7 +1834,7 @@ class Contact * @param string $reason Block reason * @return bool Whether it was successful */ - public static function block(int $cid, string $reason = null): bool + public static function block(int $cid, ?string $reason = null): bool { $return = self::update(['blocked' => true, 'block_reason' => $reason], ['id' => $cid]); @@ -3753,10 +3753,11 @@ class Contact */ public static function canReceivePrivateMessages(array $contact): bool { - $protocol = $contact['network'] ?? $contact['protocol'] ?? Protocol::PHANTOM; - $self = $contact['self'] ?? false; + $protocol = $contact['network'] ?? $contact['protocol'] ?? Protocol::PHANTOM; + $self = $contact['self'] ?? false; + $type = $contact['contact-type'] ?? Contact::TYPE_UNKNOWN; - return in_array($protocol, [Protocol::DFRN, Protocol::DIASPORA, Protocol::ACTIVITYPUB]) && !$self; + return in_array($protocol, [Protocol::DFRN, Protocol::DIASPORA, Protocol::ACTIVITYPUB]) && !$self && ($type != Contact::TYPE_COMMUNITY); } /** diff --git a/src/Model/Event.php b/src/Model/Event.php index 11fe8a9b4b..730d6082a3 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -886,6 +886,7 @@ class Event $dformat = DI::l10n()->t('l F d, Y \@ g:i A'); // Friday January 18, 2011 @ 8:01 AM. $dformat_short = DI::l10n()->t('D g:i A'); // Fri 8:01 AM. $tformat = DI::l10n()->t('g:i A'); // 8:01 AM. + $tzformat = DI::l10n()->t('e'); // Atlantic/Azores. // Convert the time to different formats. $dtstart_dt = DI::l10n()->getDay(DateTimeFormat::local($item['event-start'], $dformat)); @@ -896,6 +897,7 @@ class Event $date_short = DateTimeFormat::local($item['event-start'], 'j'); $start_time = DateTimeFormat::local($item['event-start'], $tformat); $start_short = DI::l10n()->getDayShort(DateTimeFormat::local($item['event-start'], $dformat_short)); + $timezone = DateTimeFormat::local($item['event-start'], $tzformat); // If the option 'nofinisch' isn't set, we need to format the finish date/time. if (!$item['event-nofinish']) { @@ -943,6 +945,7 @@ class Event '$start_short' => $start_short, '$end_time' => $end_time, '$end_short' => $end_short, + '$timezone' => $timezone, '$author_name' => $item['author-name'], '$author_link' => $profile_link, '$author_avatar' => $item['author-avatar'], diff --git a/src/Model/Item.php b/src/Model/Item.php index 72334e4183..fa7c9eed45 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -29,6 +29,7 @@ use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Network\HTTPException\ServiceUnavailableException; use Friendica\Protocol\Activity; use Friendica\Protocol\ActivityPub; +use Friendica\Protocol\ActivityPub\Processor; use Friendica\Protocol\Delivery; use Friendica\Protocol\Diaspora; use Friendica\Util\DateTimeFormat; @@ -39,7 +40,6 @@ use Friendica\Util\Proxy; use Friendica\Util\Strings; use Friendica\Util\Temporal; use GuzzleHttp\Psr7\Uri; -use LanguageDetection\Language; class Item { @@ -158,6 +158,7 @@ class Item const CANT_REPLY = 1; const CANT_LIKE = 2; const CANT_ANNOUNCE = 4; + const CANT_QUOTE = 8; /** * Update existing item entries @@ -995,6 +996,10 @@ class Item return 0; } + if (!isset($item['restrictions']) || is_null($item['restrictions'])) { + $item['restrictions'] = Processor::getRestrictions($item['uri-id'], $item['author-id'], $item['uid']); + } + $post_user_id = Post\User::insert($item['uri-id'], $item['uid'], $item); if (!$post_user_id) { DI::logger()->notice('Post-User is already inserted - aborting', ['uid' => $item['uid'], 'uri-id' => $item['uri-id']]); @@ -1313,14 +1318,16 @@ class Item return; } - $languages = $item['language'] ? array_keys(json_decode($item['language'], true)) : []; + $languages = $item['language'] ? json_decode($item['language'], true) : []; + $quality = DI::config()->get('system', 'relay_language_quality'); foreach (Tag::getUIDListByURIId($item['uri-id']) as $uid => $tags) { if (!empty($languages)) { $keep = false; $user_languages = User::getWantedLanguages($uid); foreach ($user_languages as $language) { - if (in_array($language, $languages)) { + if (in_array($language, array_keys($languages)) && $languages[$language] > $quality) { + DI::logger()->debug('Wanted language found', ['uid' => $uid, 'language' => $language, 'quality' => $languages[$language], 'limit' => $quality]); $keep = true; } } @@ -1830,7 +1837,7 @@ class Item * @return string Unique guid * @throws \Exception */ - public static function guidFromUri(string $uri, string $host = null): string + public static function guidFromUri(string $uri, ?string $host = null): string { // Our regular guid routine is using this kind of prefix as well // We have to avoid that different routines could accidentally create the same value @@ -2232,7 +2239,7 @@ class Item * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function fixPrivatePhotos(string $s, int $uid, array $item = null, int $cid = 0): string + public static function fixPrivatePhotos(string $s, int $uid, ?array $item = null, int $cid = 0): string { if (DI::config()->get('system', 'disable_embedded')) { return $s; @@ -2498,7 +2505,7 @@ class Item * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function performActivity(int $item_id, string $verb, int $uid, string $allow_cid = null, string $allow_gid = null, string $deny_cid = null, string $deny_gid = null): bool + public static function performActivity(int $item_id, string $verb, int $uid, ?string $allow_cid = null, ?string $allow_gid = null, ?string $deny_cid = null, ?string $deny_gid = null): bool { if (empty($uid)) { return false; @@ -2953,14 +2960,14 @@ class Item if (!empty($shared_item['uri-id'])) { $shared_uri_id = $shared_item['uri-id']; $shared_links[] = strtolower($shared_item['plink']); - $sharedSplitAttachments = DI::postMediaRepository()->splitAttachments($shared_uri_id, [], $shared_item['has-media']); + $sharedSplitAttachments = DI::postMediaRepository()->splitAttachments($shared_uri_id, [], $shared_item['has-media'], $uid != 0); $shared_links = array_merge($shared_links, $sharedSplitAttachments['visual']->column('url')); $shared_links = array_merge($shared_links, $sharedSplitAttachments['link']->column('url')); $shared_links = array_merge($shared_links, $sharedSplitAttachments['additional']->column('url')); $item['body'] = self::replaceVisualAttachments($sharedSplitAttachments['visual'], $item['body']); } - $itemSplitAttachments = DI::postMediaRepository()->splitAttachments($item['uri-id'], $shared_links, $item['has-media'] ?? false); + $itemSplitAttachments = DI::postMediaRepository()->splitAttachments($item['uri-id'], $shared_links, $item['has-media'] ?? false, $uid != 0); $item['body'] = self::replaceVisualAttachments($itemSplitAttachments['visual'], $item['body'] ?? ''); self::putInCache($item); @@ -3034,8 +3041,9 @@ class Item if (!empty($sharedSplitAttachments)) { $s = self::addGallery($s, $sharedSplitAttachments['visual']); $s = self::addVisualAttachments($sharedSplitAttachments['visual'], $shared_item, $s, true, $uid); - $s = self::addLinkAttachment($shared_uri_id ?: $item['uri-id'], $sharedSplitAttachments, $body, $s, true, $quote_shared_links, $uid); + $s = self::addLinkAttachment($shared_uri_id ?: $item['uri-id'], $sharedSplitAttachments, $body, $s, true, $quote_shared_links, $uid, $shared_item); $s = self::addNonVisualAttachments($sharedSplitAttachments['additional'], $item, $s); + $s = self::addHiddenAttachments($sharedSplitAttachments['hidden'], $item, $s); $body = BBCode::removeSharedData($body); } @@ -3047,8 +3055,9 @@ class Item $s = self::addGallery($s, $itemSplitAttachments['visual']); $s = self::addVisualAttachments($itemSplitAttachments['visual'], $item, $s, false, $uid); - $s = self::addLinkAttachment($item['uri-id'], $itemSplitAttachments, $body, $s, false, $shared_links, $uid); + $s = self::addLinkAttachment($item['uri-id'], $itemSplitAttachments, $body, $s, false, $shared_links, $uid, $item); $s = self::addNonVisualAttachments($itemSplitAttachments['additional'], $item, $s); + $s = self::addHiddenAttachments($itemSplitAttachments['hidden'], $item, $s); $s = self::addQuestions($item, $s); // Map. @@ -3069,7 +3078,7 @@ class Item $s .= $shared_html; } - $s = DI::postMediaRepository()->addEmbed($s, $uid, $item['uri-id']); + $s = DI::postMediaRepository()->addEmbed($s, $uid, $item['uri-id'], $uid != 0); $s = HTML::applyContentFilter($s, $filter_reasons); @@ -3131,6 +3140,7 @@ class Item */ private static function addGallery(string $s, PostMedias $PostMedias): string { + /** @var PostMedia $PostMedia */ foreach ($PostMedias as $PostMedia) { if (!$PostMedia->preview || ($PostMedia->type !== Post\Media::IMAGE)) { continue; @@ -3235,6 +3245,7 @@ class Item { DI::profiler()->startRecording('rendering'); + /** @var PostMedia $PostMedia */ foreach ($PostMedias as $PostMedia) { if ($PostMedia->preview) { if (DI::baseUrl()->isLocalUri($PostMedia->preview)) { @@ -3279,6 +3290,7 @@ class Item $images = new PostMedias(); // @todo In the future we should make a single for the template engine with all media in it. This allows more flexibilty. + /** @var PostMedia $PostMedia */ foreach ($PostMedias as $PostMedia) { if (self::containsLink($item['body'], $PostMedia->preview ?? $PostMedia->url, $PostMedia->type) || self::containsEmbed($item['body'], $PostMedia->url)) { continue; @@ -3359,19 +3371,24 @@ class Item * @param bool $shared * @param array $ignore_links A list of URLs to ignore * @param int $uid + * @param array $item * @return string modified content * @throws InternalServerErrorException * @throws ServiceUnavailableException */ - private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links, int $uid): string + private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links, int $uid, array $item): string { DI::profiler()->startRecording('rendering'); // Don't show a preview when there is a visual attachment (audio or video) - $types = $attachments['visual']->column('type'); - $preview = !in_array(PostMedia::TYPE_IMAGE, $types) && !in_array(PostMedia::TYPE_VIDEO, $types); + $types = $attachments['visual']->column('type'); + $preview = !in_array(PostMedia::TYPE_IMAGE, $types) && !in_array(PostMedia::TYPE_VIDEO, $types); + $has_media = in_array($item['post-type'] ?? null, [Item::PT_AUDIO, Item::PT_VIDEO]); + $is_article = false; /** @var ?PostMedia $attachment */ $attachment = null; + + /** @var PostMedia $PostMedia */ foreach ($attachments['link'] as $PostMedia) { $found = false; foreach ($ignore_links as $ignore_link) { @@ -3409,7 +3426,9 @@ class Item 'embed_html' => $attachment->embedHtml, 'embed_width' => $attachment->embedWidth, 'embed_height' => $attachment->embedHeight, + 'page_type' => $attachment->pageType, ]; + $is_article = $attachment->isArticle(); if ($preview && $attachment->preview) { if ($attachment->previewWidth >= 500) { @@ -3459,8 +3478,13 @@ class Item } // @todo Use a template - $preview_mode = DI::pConfig()->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_LARGE); - if ($preview_mode != BBCode::PREVIEW_NONE && !self::containsEmbed($body, $data['url'])) { + $preview_mode = DI::pConfig()->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_AUTO); + if ($uid == 0) { + $preview_mode = BBCode::PREVIEW_NO_IMAGE; + } elseif ($preview_mode == BBCode::PREVIEW_AUTO) { + $preview_mode = $is_article ? BBCode::PREVIEW_SMALL : BBCode::PREVIEW_LARGE; + } + if (!$has_media && $preview_mode != BBCode::PREVIEW_NONE && !self::containsEmbed($body, $data['url'])) { $rendered = BBCode::convertAttachment('', BBCode::INTERNAL, $data, $uriid, $preview_mode, DI::pConfig()->get($uid, 'system', 'embed_remote_media', false)); } elseif (!self::containsLink($content, $data['url'], Post\Media::HTML)) { $rendered = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/link.tpl'), [ @@ -3502,6 +3526,7 @@ class Item { DI::profiler()->startRecording('rendering'); $trailing = ''; + /** @var PostMedia $PostMedia */ foreach ($PostMedias as $PostMedia) { if (strpos($item['body'], (string)$PostMedia->url)) { continue; @@ -3535,6 +3560,36 @@ class Item return $content; } + /** + * Add hidden attachments message to the content + * + * @param PostMedias $PostMedias + * @param array $item + * @param string $content + * @return string modified content + */ + private static function addHiddenAttachments(PostMedias $PostMedias, array $item, string $content): string + { + if (count($PostMedias) == 0) { + return $content; + } + + + $plink = self::getPlink($item); + + if (isset($plink['href']) && !DI::baseUrl()->isLocalUrl($plink['href'])) { + $message = DI::l10n()->t('The media in this post is not displayed to visitors. To view it, please go to the original post.', $plink['href']); + } else { + $message = DI::l10n()->t('The media in this post is not displayed to visitors. To view it, please log in.'); + } + + $media = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/hidden.tpl'), [ + 'message' => $message, + ]); + + return $media . $content; + } + private static function addQuestions(array $item, string $content): string { DI::profiler()->startRecording('rendering'); @@ -3591,7 +3646,7 @@ class Item $plink = $item['uri']; } - if (($item['post-reason'] == self::PR_ANNOUNCEMENT) && ($item['owner-contact-type'] == Contact::TYPE_COMMUNITY) && ($item['owner-network'] == Protocol::DFRN)) { + if (($item['owner-contact-type'] == Contact::TYPE_COMMUNITY) && ($item['owner-network'] == Protocol::DFRN)) { $contact = Contact::getById($item['owner-id'], ['baseurl']); if (!empty($contact['baseurl'])) { $plink = $contact['baseurl'] . '/display/' . $item['guid']; diff --git a/src/Model/ItemHelper.php b/src/Model/ItemHelper.php index 686549b4f9..4b348e4964 100644 --- a/src/Model/ItemHelper.php +++ b/src/Model/ItemHelper.php @@ -389,6 +389,10 @@ final class ItemHelper return true; } + if (($restrictions & Item::CANT_QUOTE) && (!empty($item['quote-uri']) || !empty($item['quote-uri-id']))) { + return true; + } + return false; } diff --git a/src/Model/Mail.php b/src/Model/Mail.php index 8366e91654..f42f67d3ad 100644 --- a/src/Model/Mail.php +++ b/src/Model/Mail.php @@ -223,7 +223,7 @@ class Mail } if ($post_id) { - Worker::add(Worker::PRIORITY_HIGH, "Notifier", Delivery::MAIL, $post_id); + Worker::add(Worker::PRIORITY_HIGH, "Notifier", Delivery::MAIL, $post_id, $sender_uid); return intval($post_id); } else { return -3; diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 74edaf360d..833834e771 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -436,6 +436,10 @@ class Photo $storage = ''; $img_str = $image->asString(); + if (!is_string($img_str)) { + return false; + } + try { if (DBA::isResult($existing_photo)) { $backend_ref = (string)$existing_photo['backend-ref']; @@ -1389,8 +1393,10 @@ class Photo $resource_id = self::newResource(); $album = DI::l10n()->t(self::BANNER_PHOTOS); - if ($width > 960) { - $image->scaleDown(960); + $max_banner_width = DI::config()->get('system', 'max_banner_width'); + + if ($width > $max_banner_width && $max_banner_width > 0) { + $image->scaleDown($max_banner_width); } $r = self::store($image, $uid, 0, $resource_id, $filename, $album, 3, self::USER_BANNER); diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 764175d629..f75d8adfff 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -7,6 +7,7 @@ namespace Friendica\Model\Post; +use FFMpeg\FFMpeg; use Friendica\Content\PageInfo; use Friendica\Content\Text\BBCode; use Friendica\Core\Protocol; @@ -126,7 +127,7 @@ class Media { $fields = ['mimetype', 'height', 'width', 'size', 'preview', 'preview-height', 'preview-width', 'blurhash', 'description']; foreach ($fields as $field) { - if (empty($media[$field])) { + if (!isset($media[$field]) || is_null($media[$field]) || $media[$field] === '') { unset($media[$field]); } } @@ -172,6 +173,22 @@ class Media '" type="' . $media['mimetype'] . '" title="' . $media['description'] . '"[/attach]'; } + private static function setModified(array $media, string $lastModified): array + { + if (isset($media['modified']) && $media['modified'] != '') { + return $media; + } + + if ($lastModified == '') { + return $media; + } + + $media['modified'] = DateTimeFormat::utc($lastModified); + $media['published'] = $media['published'] ?? $media['modified']; + + return $media; + } + /** * Fetch additional data for the provided media array * @@ -203,7 +220,7 @@ class Media // Workaround for systems that can't handle a HEAD request if (!$curlResult->isSuccess() && in_array($curlResult->getReturnCode(), [400, 403, 405])) { - $curlResult = DI::httpClient()->get($media['url'], HttpClientAccept::AS_DEFAULT, [HttpClientOptions::TIMEOUT => $timeout, HttpClientOptions::HEADERS => ['Range' => 'bytes=0-100000']]); + $curlResult = DI::httpClient()->get($media['url'], HttpClientAccept::AS_DEFAULT, [HttpClientOptions::TIMEOUT => $timeout, HttpClientOptions::HEADERS => ['Range' => 'bytes=0-100000'], HttpClientOptions::REQUEST => HttpClientRequest::CONTENTTYPE]); $is_head = false; } if ($curlResult->isSuccess()) { @@ -213,12 +230,7 @@ class Media if (empty($media['size']) && $is_head) { $media['size'] = (int)($curlResult->getHeader('Content-Length')[0] ?? strlen($curlResult->getBodyString() ?? '')); } - if (empty($media['modified']) && !empty($curlResult->getHeader('Last-Modified')[0])) { - $media['modified'] = DateTimeFormat::utc($curlResult->getHeader('Last-Modified')[0]); - if (empty($media['published'])) { - $media['published'] = $media['modified']; - } - } + $media = self::setModified($media, $curlResult->getHeader('Last-Modified')[0] ?? ''); } else { DI::logger()->notice('Could not fetch head', ['media' => $media, 'code' => $curlResult->getReturnCode()]); } @@ -256,7 +268,11 @@ class Media if ($media['type'] === self::VIDEO) { $media = self::getVideoInformationByFFMPEG($media); - $media = self::getVideoDimensionsByID3($media, false); + $media = self::getVideoDimensionsByID3($media); + } + + if ($media['type'] === self::HLS) { + $media = self::getHLSVideoDimensions($media); } if (in_array($media['type'], [self::TEXT, self::ACTIVITY, self::LD, self::JSON, self::HTML, self::XML, self::PLAIN])) { @@ -479,18 +495,20 @@ class Media $media['embed-html'] = $data['embed']['html'] ?? null; $media['embed-height'] = $data['embed']['height'] ?? null; $media['embed-width'] = $data['embed']['width'] ?? null; + $media['page-type'] = $data['pagetype'] ?? null; $media['language'] = $data['language'] ?? null; $media['published'] = $data['published'] ?? null; $media['modified'] = $data['modified'] ?? null; + $media['schematypes'] = isset($data['schematypes']) ? json_encode($data['schematypes']) : null; - if (DI::config()->get('system', 'add_page_media')) { - if (!empty($data['audio'])) { + if (!isset($media['player-url']) && !isset($media['embed-html']) && DI::config()->get('system', 'add_page_media')) { + if (isset($data['audio']) && sizeof($data['audio']) == 1) { foreach ($data['audio'] as $entry) { self::insertMedia($entry, $media['uri-id']); } } - if (!empty($data['video'])) { + if (isset($data['video']) && sizeof($data['video']) == 1) { foreach ($data['video'] as $entry) { self::insertMedia($entry, $media['uri-id']); } @@ -506,11 +524,6 @@ class Media return; } - if (($element['mimetype'] ?? '') === 'application/x-mpegURL') { - // Until we can detect live streaming, we don't store HLS streams - return; - } - $media = ['uri-id' => $uri_id]; $media['type'] = Post\Media::UNKNOWN; $media['url'] = $element['src']; @@ -599,9 +612,11 @@ class Media if ($filetype == 'image') { $type = self::IMAGE; + } elseif (($filetype == 'video') && in_array($subtype, ['x-mpegurl', 'mpegurl'])) { + $type = self::HLS; } elseif ($filetype == 'video') { $type = self::VIDEO; - } elseif (($filetype == 'audio') && ($subtype == 'x-mpegurl')) { + } elseif (($filetype == 'audio') && in_array($subtype, ['x-mpegurl', 'mpegurl'])) { $type = self::HLS; } elseif ($filetype == 'audio') { $type = self::AUDIO; @@ -615,7 +630,7 @@ class Media $type = self::TEXT; } elseif (($filetype == 'application') && ($subtype == 'x-bittorrent')) { $type = self::TORRENT; - } elseif (($filetype == 'application') && in_array($subtype, ['vnd.apple.mpegurl', 'x-mpegurl'])) { + } elseif (($filetype == 'application') && in_array($subtype, ['vnd.apple.mpegurl', 'x-mpegurl', 'mpegurl'])) { $type = self::HLS; } elseif (($filetype == 'application') && ($subtype == 'activity+json')) { $type = self::ACTIVITY; @@ -646,7 +661,7 @@ class Media return $media; } - if (isset($media['width']) && isset($media['height']) && $media['width'] > 0 && $media['height'] > 0 && isset($media['blurhash'])) { + if (isset($media['width']) && isset($media['height']) && is_numeric($media['width']) && is_numeric($media['height']) && isset($media['blurhash'])) { return $media; } @@ -660,6 +675,34 @@ class Media $media['height'] = $image->getHeight(); DI::logger()->debug('Detected video dimensions via FFMpeg preview', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'width' => $media['width'], 'height' => $media['height']]); return $media; + } else { + try { + $ffmpeg = FFMpeg::create(); + /** @var \FFMpeg\Media\Video $video */ + $video = $ffmpeg->open($media['url']); + + $has_video = false; + $has_audio = false; + foreach ($video->getStreams() as $stream) { + if ($stream->isVideo()) { + $has_video = true; + + $media['width'] = $stream->get('width'); + $media['height'] = $stream->get('height'); + DI::logger()->debug('Detected video dimensions via FFMpeg', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'width' => $media['width'], 'height' => $media['height']]); + } + if ($stream->isAudio()) { + $has_audio = true; + } + } + if ($has_audio && !$has_video) { + $media['width'] = 0; + $media['height'] = 0; + DI::logger()->debug('Detected audio file via FFMpeg', ['uri-id' => $media['uri-id'], 'url' => $media['url']]); + } + } catch (\Throwable $th) { + DI::logger()->notice('Got exception', ['url' => $media['url'], 'code' => $th->getCode(), 'message' => $th->getMessage()]); + } } return $media; @@ -669,35 +712,29 @@ class Media * Fetch video dimensions using getID3 * * @param array $media Media array - * @param bool $full_file If true, the whole video will be fetched * @return array media with added dimensions */ - private static function getVideoDimensionsByID3(array $media, bool $full_file): array + private static function getVideoDimensionsByID3(array $media): array { - if (isset($media['width']) && isset($media['height']) && $media['width'] > 0 && $media['height'] > 0) { + if (isset($media['width']) && isset($media['height']) && is_numeric($media['width']) && is_numeric($media['height'])) { return $media; } - DI::logger()->debug('Fetch video dimensions', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'full_file' => $full_file]); + DI::logger()->debug('Fetch video dimensions', ['uri-id' => $media['uri-id'], 'url' => $media['url']]); $timestamp = microtime(true); $timeout = DI::config()->get('system', 'xrd_timeout'); - $options = $full_file ? [HttpClientOptions::TIMEOUT => $timeout] : [HttpClientOptions::TIMEOUT => $timeout, HttpClientOptions::HEADERS => ['Range' => 'bytes=0-1000000']]; - $curlResult = DI::httpClient()->get($media['url'], HttpClientAccept::AS_DEFAULT, $options); + $options = [HttpClientOptions::TIMEOUT => $timeout, HttpClientOptions::HEADERS => ['Range' => 'bytes=0-1000000'], HttpClientOptions::REQUEST => HttpClientRequest::MEDIAVERIFIER]; + $curlResult = DI::httpClient()->get($media['url'], HttpClientAccept::VIDEO, $options); if (!$curlResult->isSuccess()) { - DI::logger()->notice('Could not fetch video', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'full_file' => $full_file, 'code' => $curlResult->getReturnCode()]); + DI::logger()->notice('Could not fetch video', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'code' => $curlResult->getReturnCode()]); return $media; } - if ((!isset($media['modified']) || !$media['modified']) && isset($curlResult->getHeader('Last-Modified')[0]) && $curlResult->getHeader('Last-Modified')[0] != '') { - $media['modified'] = DateTimeFormat::utc($curlResult->getHeader('Last-Modified')[0]); - if (!isset($media['published']) || !$media['published']) { - $media['published'] = $media['modified']; - } - } + $media = self::setModified($media, $curlResult->getHeader('Last-Modified')[0] ?? ''); $video = $curlResult->getBodyString() ?? ''; if (!$video) { - DI::logger()->notice('Empty video content', ['uri-id' => $media['uri-id'], 'media' => $media, 'full_file' => $full_file]); + DI::logger()->notice('Empty video content', ['uri-id' => $media['uri-id'], 'media' => $media]); return $media; } @@ -708,28 +745,68 @@ class Media unlink($tempfile); $runtime = number_format(microtime(true) - $timestamp, 3); - // @todo When we find a way to read the video file in chunks, we can enable this part again. - //if (isset($info['error']) && !$full_file && substr($info['error'][0], 0, 14) == 'Atom at offset') { - // DI::logger()->info('Detection failed for shortened file, trying the full file now.', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url'], 'full_file' => $full_file, 'error' => $info['error']]); - // return self::getVideoDimensions($media, true); - //} - - if (isset($info['error'])) { - DI::logger()->info('Error analyzing video', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url'], 'full_file' => $full_file, 'error' => $info['error']]); - } elseif (isset($info['video']['resolution_x']) && isset($info['video']['resolution_y'])) { + if (isset($info['video']['resolution_x']) && isset($info['video']['resolution_y'])) { $media['width'] = $info['video']['resolution_x']; $media['height'] = $info['video']['resolution_y']; - DI::logger()->debug('Detected video dimensions', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url'], 'full_file' => $full_file, 'width' => $media['width'], 'height' => $media['height']]); + DI::logger()->debug('Detected video dimensions', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url'], 'width' => $media['width'], 'height' => $media['height']]); } elseif (isset($info['audio'])) { $media['width'] = 0; $media['height'] = 0; - DI::logger()->debug('Detected audio file', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url'], 'full_file' => $full_file]); + DI::logger()->debug('Detected audio file', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url']]); + } elseif (isset($info['error'])) { + DI::logger()->info('Error analyzing video', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url'], 'error' => $info['error']]); } else { - DI::logger()->info('No video dimensions found', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url'], 'full_file' => $full_file, 'info' => $info]); + DI::logger()->info('No video dimensions found', ['runtime' => $runtime, 'uri-id' => $media['uri-id'], 'url' => $media['url'], 'info' => $info]); } return $media; } + /** + * Fetch HLS video dimensions from the playlist + * + * @param array $media Media array + * @return array media with added dimensions + */ + private static function getHLSVideoDimensions(array $media): array + { + if (isset($media['width']) && isset($media['height']) && is_numeric($media['width']) && is_numeric($media['height'])) { + return $media; + } + + $resolutions = []; + + $curlResult = DI::httpClient()->get($media['url'], HttpClientAccept::HLS, [HttpClientOptions::REQUEST => HttpClientRequest::MEDIAVERIFIER]); + if (!$curlResult->isSuccess()) { + DI::logger()->notice('Could not fetch video', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'code' => $curlResult->getReturnCode()]); + return $media; + } + + $media = self::setModified($media, $curlResult->getHeader('Last-Modified')[0] ?? ''); + + foreach (explode("\n", $curlResult->getBodyString() ?? '') as $line) { + if (strpos(trim($line), '#EXT-X-STREAM-INF') === 0) { + if (preg_match('/RESOLUTION=([\d]+)x([\d]+)/', $line, $matches)) { + $resolutions[$matches[1]] = [(int)$matches[1], (int)$matches[2]]; + } + } + } + + if (!$resolutions) { + DI::logger()->debug('No resolutions found', ['uri-id' => $media['uri-id'], 'url' => $media['url']]); + return $media; + } + + krsort($resolutions); + $resolution = current($resolutions); + + $media['width'] = $resolution[0]; + $media['height'] = $resolution[1]; + + DI::logger()->debug('Detected HLS resolutions', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'resolution' => $resolution]); + + return $media; + } + /** * Tests for path patterns that are used for picture links in Friendica * diff --git a/src/Model/Tag.php b/src/Model/Tag.php index de4beb08ec..3a5cf1fef4 100644 --- a/src/Model/Tag.php +++ b/src/Model/Tag.php @@ -48,6 +48,7 @@ class Tag const CAN_ANNOUNCE = 20; const CAN_LIKE = 21; const CAN_REPLY = 22; + const CAN_QUOTE = 23; const ACCOUNT = 1; const GENERAL_COLLECTION = 2; @@ -71,7 +72,7 @@ class Tag * @param integer $target Target (default: null) * @return void */ - public static function store(int $uriId, int $type, string $name, string $url = '', int $target = null) + public static function store(int $uriId, int $type, string $name, string $url = '', ?int $target = null) { if ($type == self::HASHTAG) { // Trim Unicode non-word characters @@ -120,7 +121,7 @@ class Tag } if (empty($cid)) { - if (!in_array($type, [self::TO, self::CC, self::BTO, self::BCC, self::AUDIENCE, self::ATTRIBUTED])) { + if (!in_array($type, [self::TO, self::CC, self::BTO, self::BCC, self::AUDIENCE, self::ATTRIBUTED, self::CAN_ANNOUNCE, self::CAN_LIKE, self::CAN_REPLY, self::CAN_QUOTE])) { if (($type != self::HASHTAG) && !empty($url) && ($url != $name)) { $url = strtolower($url); } else { @@ -212,7 +213,7 @@ class Tag * @param int $type Type of tag * @return int Tag id */ - public static function getID(string $name, string $url = '', int $type = null): int + public static function getID(string $name, string $url = '', ?int $type = null): int { $fields = ['name' => substr($name, 0, 96), 'url' => $url]; @@ -268,7 +269,7 @@ class Tag * * @return array Tag list */ - public static function getFromBody(string $body, string $tags = null): array + public static function getFromBody(string $body, ?string $tags = null): array { if (is_null($tags)) { $tags = self::TAG_CHARACTER[self::HASHTAG] . self::TAG_CHARACTER[self::MENTION] . self::TAG_CHARACTER[self::EXCLUSIVE_MENTION]; @@ -289,7 +290,7 @@ class Tag * @param string $tags Accepted tags * @return void */ - public static function storeFromBody(int $uriId, string $body, string $tags = null) + public static function storeFromBody(int $uriId, string $body, ?string $tags = null) { $item = ['uri-id' => $uriId, 'body' => $body, 'quote-uri-id' => null]; self::storeFromArray($item, $tags); @@ -302,7 +303,7 @@ class Tag * @param string $tags Accepted tags * @return void */ - public static function storeFromArray(array $item, string $tags = null) + public static function storeFromArray(array $item, ?string $tags = null) { DI::logger()->info('Check for tags', ['uri-id' => $item['uri-id'], 'hash' => $tags]); diff --git a/src/Model/User.php b/src/Model/User.php index 5195fb77a3..7923690ca6 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -1178,9 +1178,10 @@ class User { $return = ['user' => null, 'password' => '']; - $using_invites = DI::config()->get('system', 'invitation_only'); + $using_invites = DI::config()->get('system', 'invitation_only', false); + $ignore_invites = (array_key_exists('ignore_invites', $data) && is_bool($data['ignore_invites'])) ? $data['ignore_invites'] : false; + $invite_id = (array_key_exists('invite_id', $data) && is_string($data['invite_id'])) ? trim($data['invite_id']) : ''; - $invite_id = !empty($data['invite_id']) ? trim($data['invite_id']) : ''; $username = !empty($data['username']) ? trim($data['username']) : ''; $nickname = !empty($data['nickname']) ? trim($data['nickname']) : ''; $email = !empty($data['email']) ? trim($data['email']) : ''; @@ -1201,7 +1202,9 @@ class User $password = $password1; } - if ($using_invites) { + + // Users created by the console or from the moderation page ignore invites + if ($using_invites && !$ignore_invites) { if (!$invite_id) { throw new Exception(DI::l10n()->t('An invitation is required.')); } @@ -1620,12 +1623,13 @@ class User } $result = self::create([ - 'username' => $name, - 'email' => $email, - 'nickname' => $nick, - 'verified' => 1, - 'language' => $lang, - 'photo' => $avatar + 'ignore_invites' => true, + 'username' => $name, + 'email' => $email, + 'nickname' => $nick, + 'verified' => 1, + 'language' => $lang, + 'photo' => $avatar ]); $user = $result['user']; diff --git a/src/Module/ActivityPub/Objects.php b/src/Module/ActivityPub/Objects.php index 4ebfe2724d..fa352ad87b 100644 --- a/src/Module/ActivityPub/Objects.php +++ b/src/Module/ActivityPub/Objects.php @@ -81,7 +81,13 @@ class Objects extends BaseModule $last_modified = $item['changed']; Network::checkEtagModified($etag, $last_modified); - if (empty($this->parameters['activity']) && ($item['gravity'] != Item::GRAVITY_ACTIVITY)) { + if (($this->parameters['activity'] ?? '') === 'replies') { + $posts = Post::toArray(Post::selectPosts(['uri'], ['thr-parent-id' => $item['uri-id'], 'gravity' => Item::GRAVITY_COMMENT, 'deleted' => false, 'private' => [Item::PUBLIC, Item::UNLISTED]])); + $data = ['@context' => ActivityPub::CONTEXT]; + $data['id'] = DI::baseUrl() . '/' . DI::args()->getQueryString(); + $data['type'] = 'OrderedCollection'; + $data['items'] = array_column($posts, 'uri'); + } elseif (!isset($this->parameters['activity']) && ($item['gravity'] !== Item::GRAVITY_ACTIVITY)) { $activity = ActivityPub\Transmitter::createCachedActivityFromItem($item['id'], false, true); if (empty($activity['type'])) { throw new HTTPException\NotFoundException(); @@ -99,7 +105,7 @@ class Objects extends BaseModule } elseif (empty($this->parameters['activity']) || in_array( $this->parameters['activity'], ['Create', 'Announce', 'Update', 'Like', 'Dislike', 'Accept', 'Reject', - 'TentativeAccept', 'Follow', 'Add'] + 'TentativeAccept', 'Follow', 'Add', 'Delete'] )) { $data = ActivityPub\Transmitter::createCachedActivityFromItem($item['id']); if (empty($data)) { diff --git a/src/Module/ActivityPub/QuoteAuthorization.php b/src/Module/ActivityPub/QuoteAuthorization.php new file mode 100644 index 0000000000..56d044335c --- /dev/null +++ b/src/Module/ActivityPub/QuoteAuthorization.php @@ -0,0 +1,54 @@ +parameters['guid'])) { + throw new HTTPException\BadRequestException(); + } + + if (empty($this->parameters['remote'])) { + throw new HTTPException\BadRequestException(); + } + + $local = Post::selectFirst(['uri', 'author-link'], ['guid' => $this->parameters['guid'], 'origin' => true, 'private' => [Item::PUBLIC, Item::UNLISTED]]); + if (!isset($local['uri'])) { + throw new HTTPException\NotFoundException(); + } + + $remote = Post::selectFirstPost(['uri'], ['guid' => $this->parameters['remote']]); + if (!isset($remote['uri'])) { + throw new HTTPException\NotFoundException(); + } + + $data = [ + '@context' => ActivityPub::CONTEXT, + 'type' => 'QuoteAuthorization', + 'id' => $local['uri'] . '/quote_authorization/' . $this->parameters['remote'], + 'attributedTo' => $local['author-link'], + 'interactingObject' => $remote['uri'], + 'interactionTarget' => $local['uri'] + ]; + + // Relaxed CORS header for public items + header('Access-Control-Allow-Origin: *'); + $this->jsonExit($data, 'application/activity+json'); + } +} diff --git a/src/Module/Admin/Site.php b/src/Module/Admin/Site.php index 2a3282abb3..d3542b892b 100644 --- a/src/Module/Admin/Site.php +++ b/src/Module/Admin/Site.php @@ -19,6 +19,7 @@ use Friendica\Model\User; use Friendica\Module\BaseAdmin; use Friendica\Module\Conversation\Community; use Friendica\Module\Register; +use Friendica\Protocol\ActivityPub\Processor; use Friendica\Protocol\Relay; use Friendica\Util\BasePath; use Friendica\Util\EMailer\MailBuilder; @@ -91,6 +92,8 @@ class Site extends BaseAdmin $community_page_style = (!empty($_POST['community_page_style']) ? intval(trim($_POST['community_page_style'])) : 0); $max_author_posts_community_page = (!empty($_POST['max_author_posts_community_page']) ? intval(trim($_POST['max_author_posts_community_page'])) : 0); $max_server_posts_community_page = (!empty($_POST['max_server_posts_community_page']) ? intval(trim($_POST['max_server_posts_community_page'])) : 0); + $display_local_media = !empty($_POST['display_local_media']); + $display_remote_media = !empty($_POST['display_remote_media']); $verifyssl = !empty($_POST['verifyssl']); $proxyuser = (!empty($_POST['proxyuser']) ? trim($_POST['proxyuser']) : ''); @@ -134,6 +137,7 @@ class Site extends BaseAdmin $worker_load_cooldown = (!empty($_POST['worker_load_cooldown']) ? intval($_POST['worker_load_cooldown']) : 0); $worker_fastlane = !empty($_POST['worker_fastlane']); $decoupled_receiver = (!empty($_POST['decoupled_receiver']) ? intval(trim($_POST['decoupled_receiver'])) : false); + $fetch_replies = (!empty($_POST['fetch_replies']) ? intval(trim($_POST['fetch_replies'])) : Processor::FETCH_REPLIES_ALL); $cron_interval = (!empty($_POST['cron_interval']) ? intval($_POST['cron_interval']) : 1); $worker_defer_limit = (!empty($_POST['worker_defer_limit']) ? intval($_POST['worker_defer_limit']) : 15); $worker_fetch_limit = (!empty($_POST['worker_fetch_limit']) ? intval($_POST['worker_fetch_limit']) : 1); @@ -269,6 +273,8 @@ class Site extends BaseAdmin $transactionConfig->set('system', 'community_page_style', $community_page_style); $transactionConfig->set('system', 'max_author_posts_community_page', $max_author_posts_community_page); $transactionConfig->set('system', 'max_server_posts_community_page', $max_server_posts_community_page); + $transactionConfig->set('system', 'display_local_media', $display_local_media); + $transactionConfig->set('system', 'display_remote_media', $display_remote_media); $transactionConfig->set('system', 'verifyssl', $verifyssl); $transactionConfig->set('system', 'proxyuser', $proxyuser); $transactionConfig->set('system', 'proxy', $proxy); @@ -313,6 +319,7 @@ class Site extends BaseAdmin $transactionConfig->set('system', 'worker_load_cooldown', $worker_load_cooldown); $transactionConfig->set('system', 'worker_fastlane', $worker_fastlane); $transactionConfig->set('system', 'decoupled_receiver', $decoupled_receiver); + $transactionConfig->set('system', 'fetch_replies', $fetch_replies); $transactionConfig->set('system', 'cron_interval', max($cron_interval, 1)); $transactionConfig->set('system', 'worker_defer_limit', $worker_defer_limit); $transactionConfig->set('system', 'worker_fetch_limit', max($worker_fetch_limit, 1)); @@ -381,6 +388,14 @@ class Site extends BaseAdmin } } + /* Reply fetch options */ + $fetch_replies_choices = [ + Processor::FETCH_REPLIES_ALL => DI::l10n()->t('Fetch replies on all posts'), + Processor::FETCH_REPLIES_NONE => DI::l10n()->t('Don\'t fetch replies'), + Processor::FETCH_REPLIES_FOLLOWED => DI::l10n()->t('Fetch replies on posts from followed contacts only'), + Processor::FETCH_REPLIES_INTERACTION => DI::l10n()->t('Fetch replies on posts with interactions only') + ]; + /* Community page style */ $community_page_style_choices = [ Community::DISABLED => DI::l10n()->t('No community page'), @@ -519,6 +534,8 @@ class Site extends BaseAdmin '$community_page_style' => ['community_page_style', DI::l10n()->t('Community pages for visitors'), DI::config()->get('system', 'community_page_style'), DI::l10n()->t('Which community pages should be available for visitors. Local users always see both pages.'), $community_page_style_choices], '$max_author_posts_community_page' => ['max_author_posts_community_page', DI::l10n()->t('Posts per user on community page'), DI::config()->get('system', 'max_author_posts_community_page'), DI::l10n()->t('The maximum number of posts per user on the local community page. This is useful, when a single user floods the local community page.')], '$max_server_posts_community_page' => ['max_server_posts_community_page', DI::l10n()->t('Posts per server on community page'), DI::config()->get('system', 'max_server_posts_community_page'), DI::l10n()->t('The maximum number of posts per server on the global community page. This is useful, when posts from a single server flood the global community page.')], + '$display_local_media' => ['display_local_media', DI::l10n()->t('Display local media to visitors'), DI::config()->get('system', 'display_local_media'), DI::l10n()->t('When enabled, locally stored media, such as pictures and videos, will be displayed to visitors who are not logged in. When disabled, a message will appear informing visitors that the media is only available to logged-in users.')], + '$display_remote_media' => ['display_remote_media', DI::l10n()->t('Display remote media to visitors'), DI::config()->get('system', 'display_remote_media'), DI::l10n()->t('When enabled, visitors who are not logged in will be able to view non-locally stored media such as pictures and videos. When disabled, visitors will see a message informing them that the media is available on the remote site.')], '$mail_able' => function_exists('imap_open'), '$mail_enabled' => ['mail_enabled', DI::l10n()->t('Enable Mail support'), !DI::config()->get('system', 'imap_disabled', !function_exists('imap_open')), DI::l10n()->t('Enable built-in mail support to poll IMAP folders and to reply via mail.')], '$mail_not_able' => DI::l10n()->t('Mail support can\'t be enabled because the PHP IMAP module is not installed.'), @@ -570,6 +587,7 @@ class Site extends BaseAdmin '$worker_load_cooldown' => ['worker_load_cooldown', DI::l10n()->t('Maximum load for workers'), DI::config()->get('system', 'worker_load_cooldown'), DI::l10n()->t('Maximum load that causes a cooldown before each worker function call.')], '$worker_fastlane' => ['worker_fastlane', DI::l10n()->t('Enable fastlane'), DI::config()->get('system', 'worker_fastlane'), DI::l10n()->t('When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.')], '$decoupled_receiver' => ['decoupled_receiver', DI::l10n()->t('Decoupled receiver'), DI::config()->get('system', 'decoupled_receiver'), DI::l10n()->t('Decouple incoming ActivityPub posts by processing them in the background via a worker process. Only enable this on fast systems.')], + '$fetch_replies' => ['fetch_replies', DI::l10n()->t('Fetch replies mode'), DI::config()->get('system', 'fetch_replies'), DI::l10n()->t('Missing replies can be fetched upon receipt of an ActivityPub post.'), $fetch_replies_choices], '$cron_interval' => ['cron_interval', DI::l10n()->t('Cron interval'), DI::config()->get('system', 'cron_interval'), DI::l10n()->t('Minimal period in minutes between two calls of the "Cron" worker job.')], '$worker_defer_limit' => ['worker_defer_limit', DI::l10n()->t('Worker defer limit'), DI::config()->get('system', 'worker_defer_limit'), DI::l10n()->t('Per default the systems tries delivering for 15 times before dropping it.')], '$worker_fetch_limit' => ['worker_fetch_limit', DI::l10n()->t('Worker fetch limit'), DI::config()->get('system', 'worker_fetch_limit'), DI::l10n()->t('Number of worker tasks that are fetched in a single query. Higher values should increase the performance, too high values will mostly likely decrease it. Only change it, when you know how to measure the performance of your system.')], diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index 282c15e4bc..2f6905103c 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -91,11 +91,11 @@ class Summary extends BaseAdmin // Legacy config file warning if (file_exists('.htconfig.php')) { - $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from .htconfig.php. See the Config help page for help with the transition.', DI::baseUrl() . '/help/Config'); + $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from .htconfig.php. See the Config help page for help with the transition.', DI::baseUrl() . '/help/admin/config'); } if (file_exists('config/local.ini.php')) { - $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from config/local.ini.php. See the Config help page for help with the transition.', DI::baseUrl() . '/help/Config'); + $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from config/local.ini.php. See the Config help page for help with the transition.', DI::baseUrl() . '/help/admin/config'); } // Check server vitality @@ -105,7 +105,7 @@ class Summary extends BaseAdmin '%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help.', $well_known, $well_known, - DI::baseUrl() . '/help/Install' + DI::baseUrl() . '/help/admin/install' ); } diff --git a/src/Module/BaseSearch.php b/src/Module/BaseSearch.php index 2a3bc8af02..a9ce8345f9 100644 --- a/src/Module/BaseSearch.php +++ b/src/Module/BaseSearch.php @@ -111,8 +111,10 @@ class BaseSearch extends BaseModule protected static function printResult(ResultList $results, Pager $pager, string $header = ''): string { if ($results->getTotal() == 0) { - DI::sysmsg()->addNotice(DI::l10n()->t('No matches')); - return ''; + $o = Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [ + '$title' => DI::l10n()->t('No results.') + ]); + return $o; } $filtered = 0; diff --git a/src/Module/Contact/Follow.php b/src/Module/Contact/Follow.php index 72c5238184..4aac790b10 100644 --- a/src/Module/Contact/Follow.php +++ b/src/Module/Contact/Follow.php @@ -159,7 +159,7 @@ class Follow extends BaseModule '$action' => $requestUrl, '$name' => $contact['name'], - '$url' => $contact['url'], + '$url' => $contact['alias'] ?: $contact['url'], '$zrl' => OpenWebAuth::getZrlUrl($contact['url']), '$myaddr' => $myaddr, '$keywords' => $contact['keywords'], @@ -173,7 +173,8 @@ class Follow extends BaseModule if (!in_array($protocol, [Protocol::PHANTOM, Protocol::MAIL])) { $this->page['aside'] = VCard::getHTML($contact, false, true); - $output .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), + $output .= Renderer::replaceMacros( + Renderer::getMarkupTemplate('section_title.tpl'), ['$title' => $this->t('Posts and Replies')] ); diff --git a/src/Module/Contact/MatchInterests.php b/src/Module/Contact/MatchInterests.php index 69713ef746..3e13caf1da 100644 --- a/src/Module/Contact/MatchInterests.php +++ b/src/Module/Contact/MatchInterests.php @@ -85,8 +85,11 @@ class MatchInterests extends BaseModule $this->page['aside'] .= Widget::follow(); if (empty($profile['pub_keywords']) && empty($profile['prv_keywords'])) { - $this->systemMessages->addNotice($this->t('No keywords to match. Please add keywords to your profile.')); - return ''; + $o = Renderer::replaceMacros(Renderer::getMarkupTemplate('contact/list.tpl'), [ + '$title' => $this->t('Profile Match'), + '$additional_text' => $this->t('No keywords to match. Please add keywords to your profile.') + ]); + return $o; } if ($this->mode->isMobile()) { @@ -132,14 +135,16 @@ class MatchInterests extends BaseModule $entries = $this->parseContacts(json_decode($result->getBodyString()), $entries, $limit); } + $additional_text = ''; if (empty($entries)) { - $this->systemMessages->addNotice($this->t('No matches')); + $additional_text = $this->t('No matches'); } $tpl = Renderer::getMarkupTemplate('contact/list.tpl'); return Renderer::replaceMacros($tpl, [ - '$title' => $this->t('Profile Match'), - '$contacts' => array_slice($entries, 0, $limit), + '$title' => $this->t('Profile Match'), + '$contacts' => array_slice($entries, 0, $limit), + '$additional_text' => $additional_text, ]); } diff --git a/src/Module/Contact/Profile.php b/src/Module/Contact/Profile.php index 0bacf9f29f..d322c9bc55 100644 --- a/src/Module/Contact/Profile.php +++ b/src/Module/Contact/Profile.php @@ -22,6 +22,7 @@ use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Core\Worker; use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\Event\ArrayFilterEvent; @@ -214,6 +215,10 @@ class Profile extends BaseModule $this->updateContactFromProbe($contact['id']); } + if ($cmd === 'fetchoutbox') { + Worker::add(Worker::PRIORITY_MEDIUM, 'FetchOutbox', $contact['id'], 0); + } + if ($cmd === 'block') { if ($localRelationship->blocked) { // @TODO Backward compatibility, replace with $localRelationship->unblock() @@ -447,7 +452,7 @@ class Profile extends BaseModule '$sparkle' => $sparkle, '$url' => $url, '$profileurllabel' => $this->t('Profile URL'), - '$profileurl' => $contact['url'], + '$profileurl' => $contact['alias'] ?: $contact['url'], '$account_type' => ContactModel::getAccountType($contact['contact-type']), '$location' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['location']), '$location_label' => $this->t('Location:'), @@ -560,6 +565,16 @@ class Profile extends BaseModule ]; } + if (in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN])) { + $contact_actions['fetchoutbox'] = [ + 'label' => $this->t('Fetch latest posts'), + 'url' => 'contact/' . $contact['id'] . '/fetchoutbox?t=' . $formSecurityToken, + 'title' => '', + 'sel' => '', + 'id' => 'fetchoutbox', + ]; + } + $contact_actions['block'] = [ 'label' => $localRelationship->blocked ? $this->t('Unblock') : $this->t('Block'), 'url' => 'contact/' . $contact['id'] . '/block?t=' . $formSecurityToken, diff --git a/src/Module/Conversation/Community.php b/src/Module/Conversation/Community.php index 5bc1727f64..8787268e9f 100644 --- a/src/Module/Conversation/Community.php +++ b/src/Module/Conversation/Community.php @@ -111,7 +111,9 @@ class Community extends Timeline $items = $this->getCommunityItems(); if (!$this->database->isResult($items)) { - $this->systemMessages->addNotice($this->l10n->t('No results.')); + $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [ + '$title' => $this->l10n->t('No results.') + ]); return $o; } diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index 6e6647dbaf..7281f60153 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -166,38 +166,62 @@ class Network extends Timeline new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_START, $hook_data) ); - $o = ''; + $o = ''; + $widgetorder = json_decode($this->pConfig->get($this->session->getLocalUserId(), 'feature', 'widgetorder')); - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::CIRCLES)) { - $this->page['aside'] .= Circle::sidebarWidget($module, $module . '/circle', 'standard', $this->circleId); + if (empty($widgetorder)) { + $widgetorder = [ + Feature::CIRCLES, + Feature::GROUPS, + Feature::ARCHIVE, + Feature::NETWORKS, + Feature::ACCOUNTS, + Feature::CHANNELS, + Feature::SEARCHES, + Feature::FOLDERS, + Feature::NOSHARER, + Feature::TRENDING_TAGS + ]; } - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::GROUPS)) { - $this->page['aside'] .= GroupManager::widget($this->session->getLocalUserId()); - } - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::ARCHIVE)) { - $this->page['aside'] .= Widget::postedByYear($module . '/archive', $this->session->getLocalUserId(), false); - } - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::NETWORKS)) { - $this->page['aside'] .= Widget::networks($module, $this->network); - } - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::ACCOUNTS)) { - $this->page['aside'] .= Widget::accountTypes($module, $this->accountTypeString); - } - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::CHANNELS)) { - $this->page['aside'] .= Widget::channels($module, $this->selectedTab, $this->session->getLocalUserId()); - } - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::SEARCHES)) { - $this->page['aside'] .= Widget\SavedSearches::getHTML($this->args->getQueryString()); - } - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::FOLDERS)) { - $this->page['aside'] .= Widget::fileAs('filed', ''); - } - if (($this->channel->isTimeline($this->selectedTab) || $this->userDefinedChannel->isTimeline($this->selectedTab, $this->session->getLocalUserId())) && - !in_array($this->selectedTab, [Channel::FOLLOWERS, Channel::FORYOU, Channel::DISCOVER]) && Feature::isEnabled($this->session->getLocalUserId(), Feature::NOSHARER)) { - $this->page['aside'] .= $this->getNoSharerWidget('network'); - } - if (Feature::isEnabled($this->session->getLocalUserId(), Feature::TRENDING_TAGS)) { - $this->page['aside'] .= TrendingTags::getHTML($this->selectedTab); + + foreach ($widgetorder as $widget) { + if (Feature::isEnabled($this->session->getLocalUserId(), $widget)) { + switch ($widget) { + case Feature::CIRCLES: + $this->page['aside'] .= Circle::sidebarWidget($module, $module . '/circle', 'standard', $this->circleId); + break; + case Feature::GROUPS: + $this->page['aside'] .= GroupManager::widget($this->session->getLocalUserId()); + break; + case Feature::ARCHIVE: + $this->page['aside'] .= Widget::postedByYear($module . '/archive', $this->session->getLocalUserId(), false); + break; + case Feature::NETWORKS: + $this->page['aside'] .= Widget::networks($module, $this->network); + break; + case Feature::ACCOUNTS: + $this->page['aside'] .= Widget::accountTypes($module, $this->accountTypeString); + break; + case Feature::CHANNELS: + $this->page['aside'] .= Widget::channels($module, $this->selectedTab, $this->session->getLocalUserId()); + break; + case Feature::SEARCHES: + $this->page['aside'] .= Widget\SavedSearches::getHTML($this->args->getQueryString()); + break; + case Feature::FOLDERS: + $this->page['aside'] .= Widget::fileAs('filed', ''); + break; + case Feature::TRENDING_TAGS: + $this->page['aside'] .= TrendingTags::getHTML($this->selectedTab); + break; + case Feature::NOSHARER: + if (($this->channel->isTimeline($this->selectedTab) || $this->userDefinedChannel->isTimeline($this->selectedTab, $this->session->getLocalUserId())) && + !in_array($this->selectedTab, [Channel::FOLLOWERS, Channel::FORYOU, Channel::DISCOVER])) { + $this->page['aside'] .= $this->getNoSharerWidget('network'); + } + break; + } + } } if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'infinite_scroll', true) && ($_GET['mode'] ?? '') != 'minimal') { @@ -322,6 +346,19 @@ class Network extends Timeline $tabs = array_merge($tabs, $this->getTabArray($this->community->getTimelines(true), 'network', 'channel')); } + $menu_tab_order = json_decode($this->pConfig->get($this->session->getLocalUserId(), 'system', 'menu_timeline_order')); + if (!empty($menu_tab_order)) { + $tmp = []; + foreach ($menu_tab_order as $order) { + foreach ($tabs as $key => $val) { + if ($key == $order || $order == $val['code']) { + $tmp[$key] = $val; + } + } + } + $tabs = $tmp; + } + $hook_data = [ 'tabs' => $tabs, ]; diff --git a/src/Module/FriendSuggest.php b/src/Module/FriendSuggest.php index 4c9720a6d6..19dce9d549 100644 --- a/src/Module/FriendSuggest.php +++ b/src/Module/FriendSuggest.php @@ -91,7 +91,13 @@ class FriendSuggest extends BaseModule { $cid = intval($this->parameters['contact']); - $contact = $this->dba->selectFirst('contact', [], ['id' => $cid, 'uid' => DI::userSession()->getLocalUserId()]); + $ucid = ContactModel::getUserContactId($cid, DI::userSession()->getLocalUserId()); + if (!$ucid) { + DI::sysmsg()->addNotice($this->t('Contact not found.')); + $this->baseUrl->redirect(); + } + + $contact = ContactModel::getById($ucid); if (empty($contact)) { DI::sysmsg()->addNotice($this->t('Contact not found.')); $this->baseUrl->redirect(); diff --git a/src/Module/Help.php b/src/Module/Help.php index 59b40fd215..ca03da80d0 100644 --- a/src/Module/Help.php +++ b/src/Module/Help.php @@ -12,6 +12,7 @@ use Friendica\Content\Nav; use Friendica\Content\Text\Markdown; use Friendica\DI; use Friendica\Network\HTTPException; +use Friendica\Util\Strings; /** * Shows the friendica help based on the /doc/ directory @@ -22,34 +23,34 @@ class Help extends BaseModule { Nav::setSelected('help'); - $text = ''; + $text = ''; $filename = ''; $config = DI::config(); - $lang = DI::session()->get('language', $config->get('system', 'language')); + $lang = DI::session()->get('language', $config->get('system', 'language')); // @TODO: Replace with parameter from router if (DI::args()->getArgc() > 1) { $path = ''; // looping through the argv keys bigger than 0 to build // a path relative to /help - for ($x = 1; $x < DI::args()->getArgc(); $x ++) { + for ($x = 1; $x < DI::args()->getArgc(); $x++) { if (strlen($path)) { $path .= '/'; } $path .= DI::args()->get($x); } - $title = basename($path); - $filename = $path; - $text = self::loadDocFile('doc/' . $path . '.md', $lang); + $title = Strings::ucFirst(basename($path)); + $filename = $path; + $text = self::loadDocFile($path . '.md', $lang); DI::page()['title'] = DI::l10n()->t('Help:') . ' ' . str_replace('-', ' ', $title); } - $home = self::loadDocFile('doc/Home.md', $lang); + $home = self::loadDocFile('home.md', $lang); if (!$text) { - $text = $home; - $filename = "Home"; + $text = $home; + $filename = "home"; DI::page()['title'] = DI::l10n()->t('Help'); } else { DI::page()['aside'] = Markdown::convert($home, false); @@ -61,17 +62,18 @@ class Help extends BaseModule $html = Markdown::convert($text, false); - if ($filename !== "Home") { + if ($filename !== "home") { // create TOC but not for home - $lines = explode("\n", $html); - $toc = "

TOC

    "; + $lines = explode("\n", $html); + $back_text = DI::l10n()->t('Home'); + $toc = "

     $back_text

    TOC

      "; $lastLevel = 1; - $idNum = [0, 0, 0, 0, 0, 0, 0]; + $idNum = [0, 0, 0, 0, 0, 0, 0]; foreach ($lines as &$line) { $matches = []; if (preg_match('#([^<]+?)#i', $line, $matches)) { - $level = $matches[1]; - $anchor = urlencode($matches[2]); + $level = $matches[1]; + $anchor = strtolower(urlencode($matches[2])); if ($level < $lastLevel) { for ($k = $level; $k < $lastLevel; $k++) { $toc .= "
    "; @@ -86,11 +88,11 @@ class Help extends BaseModule $toc .= "
    • "; } - $idNum[$level] ++; + $idNum[$level]++; $href = "help/{$filename}#{$anchor}"; $toc .= "
    • " . strip_tags($line) . "
    • "; - $id = implode("_", array_slice($idNum, 1, $level)); + $id = implode("_", array_slice($idNum, 1, $level)); $line = "" . $line; $line = "" . $line; @@ -110,16 +112,25 @@ class Help extends BaseModule return $html; } - private static function loadDocFile($fileName, $lang = 'en') + private static function loadDocFile($filePath, $lang = 'en') { - $baseName = basename($fileName); - $dirName = dirname($fileName); - if (file_exists("$dirName/$lang/$baseName")) { - return file_get_contents("$dirName/$lang/$baseName"); + $baseDir = "doc"; + + // Try loading docs inside a language dir first, then try English dir, then fall back to looking at the root dir + $docPath = "$baseDir/$lang/$filePath"; + if (file_exists($docPath)) { + return file_get_contents($docPath); } - if (file_exists($fileName)) { - return file_get_contents($fileName); + $docPath = "$baseDir/en/$filePath"; + if (file_exists($docPath)) { + return file_get_contents($docPath); + } + + // Delete this once database docs have been moved into en/spec/database + $docPath = "$baseDir/$filePath"; + if (file_exists($docPath)) { + return file_get_contents($docPath); } return ''; diff --git a/src/Module/Item/Complete.php b/src/Module/Item/Complete.php new file mode 100644 index 0000000000..7982f8a0bc --- /dev/null +++ b/src/Module/Item/Complete.php @@ -0,0 +1,46 @@ +debug('Complete thread requested.', ['parameters' => $this->parameters]); + if (!DI::userSession()->isAuthenticated()) { + throw new HttpException\ForbiddenException($l10n->t('Access denied.')); + } + + if (!isset($this->parameters['id'])) { + throw new HTTPException\BadRequestException(); + } + + $itemId = intval($this->parameters['id']); + + Worker::add(Worker::PRIORITY_MEDIUM, 'FetchMissingReplies', $itemId); + + $return = [ + 'status' => 'ok', + 'item_id' => $itemId, + 'verb' => 'complete', + 'state' => 1 + ]; + + DI::logger()->debug('Complete thread executed.', ['parameters' => $this->parameters]); + $this->jsonExit($return); + } +} diff --git a/src/Module/Item/Display.php b/src/Module/Item/Display.php index e6bdf2e571..609cc12f77 100644 --- a/src/Module/Item/Display.php +++ b/src/Module/Item/Display.php @@ -31,6 +31,8 @@ use Friendica\Protocol\ActivityPub; use Friendica\Util\Profiler; use Friendica\Network\HTTPException; use Friendica\Content\Widget; +use Friendica\Core\System; +use Friendica\DI; use Psr\Log\LoggerInterface; /** @@ -87,7 +89,9 @@ class Display extends BaseModule $item = null; $itemUid = $this->session->getLocalUserId(); - $fields = ['uri-id', 'parent-uri-id', 'author-id', 'author-link', 'contact-id', 'contact-contact-type', 'body', 'uid', 'guid', 'gravity']; + $fields = ['uri-id', 'parent-uri-id', 'author-id', 'author-link', 'contact-id', 'contact-contact-type', 'body', 'uid', 'guid', 'gravity', + 'plink', 'origin', 'uri', 'post-reason', 'owner-contact-type', 'owner-network', 'owner-id', 'guid', + 'author-network', 'author-alias', 'private']; // Does the local user have this item? if ($this->session->getLocalUserId()) { @@ -124,6 +128,12 @@ class Display extends BaseModule return $displayNotFound->content(); } + $plink = Item::getPlink($item); + + if (!$this->session->getLocalUserId() && isset($plink['href']) && !DI::baseUrl()->isLocalUrl($plink['href'])) { + System::externalRedirect($plink['href']); + } + if ($item['gravity'] != Item::GRAVITY_PARENT) { $parent = Post::selectFirst($fields, [ 'uid' => [0, $itemUid], diff --git a/src/Module/Media/Attachment/Browser.php b/src/Module/Media/Attachment/Browser.php index fd46499552..45162ed794 100644 --- a/src/Module/Media/Attachment/Browser.php +++ b/src/Module/Media/Attachment/Browser.php @@ -76,12 +76,12 @@ class Browser extends BaseModule protected function map_files(array $record): array { list($m1, $m2) = explode('/', $record['filetype']); - $filetype = file_exists(sprintf('images/icons/%s.png', $m1) ? $m1 : 'text'); + $filetype = file_exists(sprintf('images/icons/%s.png', $m1)) ? $m1 : 'text'; return [ sprintf('%s/attach/%s', $this->baseUrl, $record['id']), $record['filename'], - sprintf('%s/images/icon/16/%s.png', $this->baseUrl, $filetype), + sprintf('%s/images/icons/%s.png', $this->baseUrl, $filetype), ]; } } diff --git a/src/Module/Moderation/Blocklist/Contact.php b/src/Module/Moderation/Blocklist/Contact.php index 02bb451213..5511092034 100644 --- a/src/Module/Moderation/Blocklist/Contact.php +++ b/src/Module/Moderation/Blocklist/Contact.php @@ -95,15 +95,18 @@ class Contact extends BaseModeration $t = Renderer::getMarkupTemplate('moderation/blocklist/contact.tpl'); return Renderer::replaceMacros($t, [ // strings // - '$title' => $this->t('Moderation'), - '$page' => $this->t('Remote Contact Blocklist'), - '$description' => $this->t('This page allows you to prevent any message from a remote contact to reach your node.'), - '$submit' => $this->t('Block Remote Contact'), - '$select_all' => $this->t('select all'), - '$select_none' => $this->t('select none'), - '$block' => $this->t('Block'), - '$unblock' => $this->t('Unblock'), - '$no_data' => $this->t('No remote contact is blocked from this node.'), + '$title' => $this->t('Moderation'), + '$page' => $this->t('Remote Contact Blocklist'), + '$description' => $this->t('This page allows you to prevent any message from a remote contact to reach your node.'), + '$submit' => $this->t('Block Remote Contact'), + '$importexport' => $this->t('Import/Export'), + '$import_csv' => $this->t('Import from CSV file'), + '$export_csv' => $this->t('Export to CSV file'), + '$select_all' => $this->t('select all'), + '$select_none' => $this->t('select none'), + '$block' => $this->t('Block'), + '$unblock' => $this->t('Unblock'), + '$no_data' => $this->t('No remote contact is blocked from this node.'), '$h_contacts' => $this->t('Blocked Remote Contacts'), '$h_newblock' => $this->t('Block New Remote Contact'), diff --git a/src/Module/Moderation/Blocklist/Contact/Export.php b/src/Module/Moderation/Blocklist/Contact/Export.php new file mode 100644 index 0000000000..b8039cb0cd --- /dev/null +++ b/src/Module/Moderation/Blocklist/Contact/Export.php @@ -0,0 +1,53 @@ +checkModerationAccess(); + + $condition = ['uid' => 0, 'blocked' => true, 'network' => Protocol::FEDERATED]; + $contacts = Model\Contact::selectToArray(['url', 'addr', 'alias', 'block_reason'], $condition); + + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Transfer-Encoding: Binary'); + header('Content-disposition: attachment; filename="blocked_contacts_' . date('Y-m-d') . '.csv"'); + + $output = fopen('php://output', 'w'); + + foreach ($contacts as $contact) { + // Prefer addr (user@domain), then alias, then url as fallback + $identifier = $contact['url']; + + if (!empty($contact['addr']) && strpos($contact['addr'], '@') !== false) { + $identifier = $contact['addr']; + } elseif (!empty($contact['alias'])) { + $identifier = $contact['alias']; + } + + fputcsv($output, [$identifier, $contact['block_reason'] ?? '']); + } + + fclose($output); + System::exit(); + } +} diff --git a/src/Module/Moderation/Blocklist/Contact/Import.php b/src/Module/Moderation/Blocklist/Contact/Import.php new file mode 100644 index 0000000000..cb9a96b277 --- /dev/null +++ b/src/Module/Moderation/Blocklist/Contact/Import.php @@ -0,0 +1,150 @@ +checkModerationAccess(); + + if (!isset($request['page_contactblock_upload']) && !isset($request['page_contactblock_import'])) { + return; + } + + self::checkFormSecurityTokenRedirectOnError('/moderation/blocklist/contact/import', 'moderation_contactblock_import'); + + if (isset($request['page_contactblock_upload'])) { + try { + $this->contactlist = $this->extractFromCSVFile($_FILES['listfile']['tmp_name']); + if (empty($this->contactlist)) { + $this->notices[] = $this->t('No valid contacts found in CSV file.'); + } + return; + } catch (\Throwable $e) { + $this->notices[] = $this->t('Error importing contact file: %s', $e->getMessage()); + return; + } + } elseif (isset($request['page_contactblock_import'])) { + $this->contactlist = json_decode($request['contactlist'], true); + if ($this->contactlist === null) { + $this->notices[] = $this->t('Error parsing contact data.'); + return; + } + } + + $queued = 0; + $skipped = 0; + $purge = !empty($request['purge']); + + foreach ($this->contactlist as $item) { + $contact_url = $item['url'] ?? ''; + $block_reason = $item['reason'] ?? ''; + + if (empty($contact_url)) { + $skipped++; + continue; + } + + Worker::add(Worker::PRIORITY_LOW, 'Contact\BlockByUrl', $contact_url, $block_reason, $purge); + $queued++; + } + + if ($queued > 0) { + $this->notices[] = $this->tt('%d contact blocking was queued.', '%d contact blockings were queued.', $queued); + } + if ($skipped > 0) { + $this->notices[] = $this->tt('%d contact was skipped (empty URL).', '%d contacts were skipped (empty URL).', $skipped); + } + + $this->contactlist = []; + } + + /** + * @param array $request + * @return string + * @throws HTTPException\ServiceUnavailableException + */ + protected function content(array $request = []): string + { + parent::content(); + + $t = Renderer::getMarkupTemplate('moderation/blocklist/contact/import.tpl'); + return Renderer::replaceMacros($t, [ + '$notices' => $this->notices, + '$l10n' => [ + 'return_list' => $this->t('← Return to the list'), + 'title' => $this->t('Moderation'), + 'page' => $this->t('Import a Contact Blocklist'), + 'download' => $this->t('

      Upload a CSV file with contact URLs and reasons for blocking.

      '), + 'upload' => $this->t('Upload file'), + 'contacts' => $this->t('Contacts to import'), + 'contact_url' => $this->t('Contact URL'), + 'block_reason' => $this->t('Block Reason'), + 'import' => $this->t('Import Contacts'), + 'contact_count' => $this->tt('%d total contact', '%d total contacts', count($this->contactlist)), + 'purge' => $this->t('Also purge contacts'), + 'purge_desc' => $this->t('Removes all content related to these contacts from the node. Keeps the contact records. This action cannot be undone.'), + ], + '$listfile' => ['listfile', $this->t('Contact blocklist CSV file'), '', '', $this->t('Required'), '', 'file'], + '$purge' => ['purge', $this->t('Also purge contacts'), false, $this->t('Removes all content related to these contacts from the node. Keeps the contact records. This action cannot be undone.')], + '$contactlist' => $this->contactlist, + '$form_security_token' => self::getFormSecurityToken('moderation_contactblock_import') + ]); + } + + /** + * Extracts a contact block list from the provided CSV file name. + * + * @param string $filename + * + * @return array + * @throws \Exception + */ + private function extractFromCSVFile(string $filename): array + { + $fp = fopen($filename, 'r'); + if ($fp === false) { + throw new \Exception($this->l10n->t('The file "%s" could not be opened for importing', $filename)); + } + + $contactlist = []; + while (($data = fgetcsv($fp, 1000)) !== false) { + $item = [ + 'url' => $data[0] ?? '', + 'reason' => $data[1] ?? '', + ]; + + if (!empty($item['url']) && !in_array($item, $contactlist)) { + $contactlist[] = $item; + } + } + + fclose($fp); + return $contactlist; + } +} diff --git a/src/Module/Moderation/Item/Source.php b/src/Module/Moderation/Item/Source.php index 64858294eb..018429ae06 100644 --- a/src/Module/Moderation/Item/Source.php +++ b/src/Module/Moderation/Item/Source.php @@ -47,16 +47,16 @@ class Source extends BaseModeration $guid = basename($request['guid'] ?? $this->parameters['guid'] ?? ''); $item_uri = ''; - $item_id = ''; - $terms = []; - $source = ''; + $item_id = ''; + $terms = []; + $source = ''; if (!empty($guid)) { $item = Model\Post::selectFirst(['id', 'uri-id', 'guid', 'uri'], ['guid' => $guid]); if ($item) { - $item_id = $item['id']; + $item_id = $item['id']; $item_uri = $item['uri']; - $terms = Model\Tag::getByURIId($item['uri-id'], [Model\Tag::HASHTAG, Model\Tag::MENTION, Model\Tag::IMPLICIT_MENTION]); + $terms = Model\Tag::getByURIId($item['uri-id'], [Model\Tag::HASHTAG, Model\Tag::MENTION, Model\Tag::IMPLICIT_MENTION]); $activity = Model\Post\Activity::getByURIId($item['uri-id']); if (!empty($activity)) { @@ -68,7 +68,8 @@ class Source extends BaseModeration $tpl = Renderer::getMarkupTemplate('moderation/item/source.tpl'); return Renderer::replaceMacros($tpl, [ '$l10n' => [ - 'title' => $this->t('Item Source'), + 'title' => $this->t('Moderation'), + 'page' => $this->t('Item Source'), 'itemidlbl' => $this->t('Item Id'), 'itemurilbl' => $this->t('Item URI'), 'submit' => $this->t('Submit'), @@ -79,12 +80,12 @@ class Source extends BaseModeration 'urllbl' => $this->t('URL'), 'mentionlbl' => $this->t('Mention'), 'implicitlbl' => $this->t('Implicit Mention'), - 'error' => $this->tt('Error','Errors', 1), + 'error' => $this->tt('Error', 'Errors', 1), 'notfound' => $this->t('Item not found'), 'nosource' => $this->t('No source recorded'), 'noconfig' => !$this->config->get('debug', 'store_source') ? $this->t('Please make sure the debug.store_source config key is set in config/local.config.php for future items to have sources.') : '', ], - '$guid_field' => ['guid', $this->t('Item Guid'), $guid, ''], + '$guid_field' => ['guid', '', $guid, '', '', 'autofocus', '', $this->t('Item Guid')], '$guid' => $guid, '$item_uri' => $item_uri, '$item_id' => $item_id, diff --git a/src/Module/Moderation/Report/Create.php b/src/Module/Moderation/Report/Create.php index a3887a2f82..d75e8e0fab 100644 --- a/src/Module/Moderation/Report/Create.php +++ b/src/Module/Moderation/Report/Create.php @@ -23,6 +23,7 @@ use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Moderation\Entity\Report; +use Friendica\Module\Moderation\Utils\ReportUtil; use Friendica\Module\Response; use Friendica\Navigation\SystemMessages; use Friendica\Network\HTTPException\ForbiddenException; @@ -46,13 +47,16 @@ class Create extends BaseModule private $factory; /** @var \Friendica\Moderation\Repository\Report */ private $repository; + /** @var ReportUtil */ + protected $reportUtil; - public function __construct(\Friendica\Moderation\Repository\Report $repository, \Friendica\Moderation\Factory\Report $factory, UserSession $session, App\Page $page, SystemMessages $systemMessages, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) + public function __construct(\Friendica\Moderation\Repository\Report $repository, ReportUtil $reportUtil, \Friendica\Moderation\Factory\Report $factory, UserSession $session, App\Page $page, SystemMessages $systemMessages, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->systemMessages = $systemMessages; $this->page = $page; + $this->reportUtil = $reportUtil; $this->session = $session; $this->factory = $factory; $this->repository = $repository; @@ -305,23 +309,6 @@ class Create extends BaseModule $contact = Contact::getById($request['cid']); } - switch ($request['category'] ?? 0) { - case Report::CATEGORY_SPAM: $category = $this->t('Spam'); - break; - case Report::CATEGORY_ILLEGAL: $category = $this->t('Illegal Content'); - break; - case Report::CATEGORY_SAFETY: $category = $this->t('Community Safety'); - break; - case Report::CATEGORY_UNWANTED: $category = $this->t('Unwanted Content/Behavior'); - break; - case Report::CATEGORY_VIOLATION: $category = $this->t('Rules Violation'); - break; - case Report::CATEGORY_OTHER: $category = $this->t('Other'); - break; - - default: $category = ''; - } - if (!empty($request['rule-ids'])) { $rules = array_filter(System::getRules(true), function ($rule_id) use ($request) { return in_array($rule_id, $request['rule-ids']); @@ -339,7 +326,7 @@ class Create extends BaseModule ], '$contact' => $contact, - '$category' => $category, + '$category' => $this->reportUtil->getReportCategoryName($request['category'] ?? 0), '$rules' => $rules ?? [], '$comment' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $this->session->get('report_comment') ?? '', BBCode::EXTERNAL), '$posts' => count($request['uri-ids'] ?? []), diff --git a/src/Module/Moderation/Reports.php b/src/Module/Moderation/Reports.php index 1b713abb66..859af6e7f1 100644 --- a/src/Module/Moderation/Reports.php +++ b/src/Module/Moderation/Reports.php @@ -19,6 +19,7 @@ use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\Module\BaseModeration; +use Friendica\Module\Moderation\Utils\ReportUtil; use Friendica\Module\Response; use Friendica\Navigation\SystemMessages; use Friendica\Util\DateTimeFormat; @@ -29,12 +30,15 @@ class Reports extends BaseModeration { /** @var Database */ private $database; + /** @var ReportUtil */ + protected $reportUtil; - public function __construct(Database $database, Page $page, AppHelper $appHelper, SystemMessages $systemMessages, IHandleUserSessions $session, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) + public function __construct(Database $database, Page $page, ReportUtil $reportUtil, AppHelper $appHelper, SystemMessages $systemMessages, IHandleUserSessions $session, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) { parent::__construct($page, $appHelper, $systemMessages, $session, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->database = $database; + $this->database = $database; + $this->reportUtil = $reportUtil; } protected function post(array $request = []) @@ -72,8 +76,9 @@ LIMIT ?, ?", $reports = []; while ($report = $this->database->fetch($query)) { - $report['posts'] = []; - $report['created'] = DateTimeFormat::local($report['created'], DateTimeFormat::MYSQL); + $report['posts'] = []; + $report['created'] = DateTimeFormat::local($report['created'], DateTimeFormat::MYSQL); + $report['category'] = $this->reportUtil->getReportCategoryName($report['category-id']); $reports[$report['id']] = $report; } diff --git a/src/Module/Moderation/Users/Create.php b/src/Module/Moderation/Users/Create.php index 6e16e37f4e..36a3a7a4a5 100644 --- a/src/Module/Moderation/Users/Create.php +++ b/src/Module/Moderation/Users/Create.php @@ -20,9 +20,9 @@ class Create extends BaseUsers self::checkFormSecurityTokenRedirectOnError('moderation/users/create', 'admin_users_create'); - $nu_name = $request['new_user_name'] ?? ''; + $nu_name = $request['new_user_name'] ?? ''; $nu_nickname = $request['new_user_nickname'] ?? ''; - $nu_email = $request['new_user_email'] ?? ''; + $nu_email = $request['new_user_email'] ?? ''; $nu_language = DI::config()->get('system', 'language'); if ($nu_name !== '' && $nu_email !== '' && $nu_nickname !== '') { @@ -44,18 +44,19 @@ class Create extends BaseUsers $t = Renderer::getMarkupTemplate('moderation/users/create.tpl'); return self::getTabsHTML('all') . Renderer::replaceMacros($t, [ // strings // - '$title' => $this->t('Administration'), - '$page' => $this->t('New User'), - '$submit' => $this->t('Add User'), + '$title' => $this->t('Moderation'), + '$page' => $this->t('Create user'), + '$description' => $this->t('Type in the details for the new user to be created.'), + '$submit' => $this->t('Create user'), '$form_security_token' => self::getFormSecurityToken('admin_users_create'), // values // '$query_string' => $this->args->getQueryString(), - '$newusername' => ['new_user_name', $this->t('Name'), '', $this->t('Name of the new user.')], - '$newusernickname' => ['new_user_nickname', $this->t('Nickname'), '', $this->t('Nickname of the new user.')], - '$newuseremail' => ['new_user_email', $this->t('Email'), '', $this->t('Email address of the new user.'), '', '', 'email'], + '$newusername' => ['new_user_name', '', '', '', true, 'autofocus', '', $this->t('Display name')], + '$newusernickname' => ['new_user_nickname', '', '', '', true, '', '', $this->t('Nickname')], + '$newuseremail' => ['new_user_email', '', '', '', true, 'email', '', $this->t('Email')], ]); } } diff --git a/src/Module/Moderation/Utils/ReportUtil.php b/src/Module/Moderation/Utils/ReportUtil.php new file mode 100644 index 0000000000..a06d34d5cb --- /dev/null +++ b/src/Module/Moderation/Utils/ReportUtil.php @@ -0,0 +1,41 @@ +l10n = $l10n; + } + + public function getReportCategoryName(int $category): string + { + switch ($category) { + case Report::CATEGORY_SPAM: + return $this->l10n->t('Spam'); + case Report::CATEGORY_ILLEGAL: + return $this->l10n->t('Illegal Content'); + case Report::CATEGORY_SAFETY: + return $this->l10n->t('Community Safety'); + case Report::CATEGORY_UNWANTED: + return $this->l10n->t('Unwanted Content/Behavior'); + case Report::CATEGORY_VIOLATION: + return $this->l10n->t('Rules Violation'); + case Report::CATEGORY_OTHER: + return $this->l10n->t('Other'); + default: + return ""; + }; + } +} diff --git a/src/Module/Notifications/Introductions.php b/src/Module/Notifications/Introductions.php index 363fab6b5d..860e446da3 100644 --- a/src/Module/Notifications/Introductions.php +++ b/src/Module/Notifications/Introductions.php @@ -161,7 +161,7 @@ class Introductions extends BaseNotifications $header .= ' (' . ContactSelector::networkToName($Introduction->getNetwork(), '', $gsid) . ')'; if ($Introduction->getNetwork() != Protocol::DIASPORA) { - $discard = $this->t('Discard'); + $discard = $this->t('Remove'); } else { $discard = ''; } diff --git a/src/Module/Post/Edit.php b/src/Module/Post/Edit.php index 92e86e4892..daac9aaf8d 100644 --- a/src/Module/Post/Edit.php +++ b/src/Module/Post/Edit.php @@ -99,10 +99,12 @@ class Edit extends BaseModule ]); $this->page['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('jot-header.tpl'), [ - '$ispublic' => ' ', - '$geotag' => '', - '$nickname' => $this->session->getLocalUserNickname(), - '$is_mobile' => $this->mode->isMobile(), + '$ispublic' => ' ', + '$geotag' => '', + '$nickname' => $this->session->getLocalUserNickname(), + '$postPublished' => $this->t('Post published.'), + '$goToPost' => $this->t('Go to post'), + '$is_mobile' => $this->mode->isMobile(), ]); if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) { diff --git a/src/Module/Profile/Schedule.php b/src/Module/Profile/Schedule.php index 212c02b78a..82415ce370 100644 --- a/src/Module/Profile/Schedule.php +++ b/src/Module/Profile/Schedule.php @@ -16,6 +16,8 @@ use Friendica\Model\Post; use Friendica\Module\BaseProfile; use Friendica\Network\HTTPException; use Friendica\Util\DateTimeFormat; +use Friendica\Model\Item; +use Friendica\Model\Tag; class Schedule extends BaseProfile { @@ -45,16 +47,58 @@ class Schedule extends BaseProfile $o = self::getTabsHTML('schedule', true, DI::userSession()->getLocalUserNickname(), false); $schedule = []; - $delayed = DBA::select('delayed-post', [], ['uid' => DI::userSession()->getLocalUserId()]); + $delayed = DBA::select('delayed-post', [], ['uid' => DI::userSession()->getLocalUserId()]); while ($row = DBA::fetch($delayed)) { $parameter = Post\Delayed::getParametersForid($row['id']); if (empty($parameter)) { continue; } + $parameter['item']['uri-id'] = $parameter['parameters']['wid']; + // scheduling strips [url] BBcode from hashtags so we need to add them back: + $parameter['item']['body'] = Item::setHashtags($parameter['item']['body']); + // now we need to extract them into an array: + $extracted_tags = Tag::getFromBody($parameter['item']['body']); + // then we prep the body to get rendered HTML back: + Item::prepareBody($parameter['item'], true); + // Item:prepareBody creates the tag arrays but they will be empty... + $tags = [ + 'tags' => [], + 'hashtags' => [], + 'mentions' => [], + 'implicit_mentions' => [], + ]; + // populate our $tags placeholder array: + if (!empty($extracted_tags)) { + foreach ($extracted_tags as $tag) { + $html = '' . $tag[1] . '' . $tag[3] . ''; + if ($tag[1] == "#") { + $tags['hashtags'][] = $html; + } elseif ($tag[1] == "@") { + $tags['mentions'][] = $html; + } elseif ($tag[1] == "1") { + $tags['implicit_mentions'][] = $html; + } else { // no idea what it isset + } + // tags is catch-all for all of them + $tags['tags'][] = $html; + } + } + // populate the ['item'] tag arrays... + $parameter['item']['tags'] = $tags['tags']; + $parameter['item']['hashtags'] = $tags['hashtags']; + $parameter['item']['mentions'] = $tags['mentions']; + $parameter['item']['implicit_mentions'] = $tags['implicit_mentions']; + // fetch privacy + if ($parameter['item']['private'] == 1) { + $parameter['item']['lock'] = DI::l10n()->t('Private Message'); + } + // we no return to our scheduled program... $schedule[] = [ 'id' => $row['id'], - 'scheduled_at' => DateTimeFormat::local($row['delayed']), - 'content' => BBCode::toPlaintext($parameter['item']['body'], false) + 'scheduled_at' => DateTimeFormat::local($row['delayed'], "D, d M Y H:i:s e"), + 'content' => BBCode::toPlaintext($parameter['item']['body'], false), + 'item' => $parameter['item'], + 'via' => DI::l10n()->t('via'), ]; } DBA::close($delayed); diff --git a/src/Module/Settings/Channels.php b/src/Module/Settings/Channels.php index ba553d93e7..47a7faecd0 100644 --- a/src/Module/Settings/Channels.php +++ b/src/Module/Settings/Channels.php @@ -207,7 +207,7 @@ class Channels extends BaseSettings 'exclude_tags' => ["new_exclude_tags", $this->t("Exclude Tags"), '', $exclude_tags_translation], 'min_size' => ["new_min_size", $this->t("Minimum Size"), '', $this->t('Minimum post size. Leave empty for no minimum size. The size is calculated without links, attached posts, mentions or hashtags.')], 'max_size' => ["new_max_size", $this->t("Maximum Size"), '', $this->t('Maximum post size. Leave empty for no maximum size. The size is calculated without links, attached posts, mentions or hashtags.')], - 'text_search' => ["new_text_search", $this->t("Full Text Search"), '', $this->t('Search terms for the body, supports the "boolean mode" operators from MariaDB. See the help for a complete list of operators and additional keywords: %s', 'help/Channels')], + 'text_search' => ["new_text_search", $this->t("Full Text Search"), '', $this->t('Search terms for the body, supports the "boolean mode" operators from MariaDB. See the help for a complete list of operators and additional keywords: %s', 'help/channels')], 'image' => ['new_image', $this->t("Images"), false, $this->t("Check to display images in the channel.")], 'video' => ["new_video", $this->t("Videos"), false, $this->t("Check to display videos in the channel.")], 'audio' => ["new_audio", $this->t("Audio"), false, $this->t("Check to display audio in the channel.")], diff --git a/src/Module/Settings/Connectors.php b/src/Module/Settings/Connectors.php index 7e5b57a783..0d10abd22c 100644 --- a/src/Module/Settings/Connectors.php +++ b/src/Module/Settings/Connectors.php @@ -63,15 +63,15 @@ class Connectors extends BaseSettings $this->pconfig->set($this->session->getLocalUserId(), 'system', 'api_auto_attach', intval($request['api_auto_attach'])); $this->pconfig->set($this->session->getLocalUserId(), 'system', 'article_mode', intval($request['article_mode'])); } elseif (!empty($request['mail-submit']) && function_exists('imap_open') && !$this->config->get('system', 'imap_disabled')) { - $mail_server = $request['mail_server'] ?? ''; - $mail_port = $request['mail_port'] ?? ''; + $mail_server = $request['mail_server'] ?? ''; + $mail_port = $request['mail_port'] ?? ''; $mail_ssl = strtolower(trim($request['mail_ssl'] ?? '')); - $mail_user = $request['mail_user'] ?? ''; - $mail_pass = trim($request['mail_pass'] ?? ''); - $mail_action = trim($request['mail_action'] ?? ''); - $mail_movetofolder = trim($request['mail_movetofolder'] ?? ''); - $mail_replyto = $request['mail_replyto'] ?? ''; - $mail_pubmail = $request['mail_pubmail'] ?? ''; + $mail_user = $request['mail_user'] ?? ''; + $mail_pass = trim($request['mail_pass'] ?? ''); + $mail_action = trim($request['mail_action'] ?? ''); + $mail_movetofolder = trim($request['mail_movetofolder'] ?? ''); + $mail_replyto = $request['mail_replyto'] ?? ''; + $mail_pubmail = $request['mail_pubmail'] ?? ''; if (!$this->database->exists('mailacct', ['uid' => $this->session->getLocalUserId()])) { $this->database->insert('mailacct', ['uid' => $this->session->getLocalUserId()]); @@ -118,14 +118,14 @@ class Connectors extends BaseSettings { parent::content($request); - $accept_only_sharer = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'accept_only_sharer')); + $accept_only_sharer = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'accept_only_sharer')); $enable_cw = !intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'disable_cw')); $enable_smart_shortening = !intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'no_intelligent_shortening')); - $simple_shortening = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'simple_shortening')); - $attach_link_title = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'attach_link_title')); - $api_spoiler_title = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'api_spoiler_title', true)); - $api_auto_attach = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'api_auto_attach', false)); - $article_mode = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'article_mode')); + $simple_shortening = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'simple_shortening')); + $attach_link_title = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'attach_link_title')); + $api_spoiler_title = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'api_spoiler_title', true)); + $api_auto_attach = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'api_auto_attach', false)); + $article_mode = intval($this->pconfig->get($this->session->getLocalUserId(), 'system', 'article_mode')); $connector_settings_forms = []; foreach ($this->database->selectToArray('hook', ['file', 'function'], ['hook' => 'connector_settings']) as $hook) { @@ -136,10 +136,10 @@ class Connectors extends BaseSettings $connector_settings_forms[$data['connector']] = Renderer::replaceMacros($tpl, [ '$connector' => $data['connector'], '$title' => $data['title'], - '$image' => $data['image'] ?? '', + '$image' => $data['image'] ?? '', '$enabled' => $data['enabled'] ?? true, '$open' => ($this->parameters['connector'] ?? '') === $data['connector'], - '$html' => $data['html'] ?? '', + '$html' => $data['html'] ?? '', '$submit' => $data['submit'] ?? $this->t('Save Settings'), ]); } @@ -161,7 +161,7 @@ class Connectors extends BaseSettings $mail_disabled = $this->t('Email access is disabled on this site.'); } - $mail_server = $mail_account['server'] ?? ''; + $mail_server = $mail_account['server'] ?? ''; $mail_port = (!empty($mail_account['port']) && is_numeric($mail_account['port'])) ? (int)$mail_account['port'] : ''; $mail_ssl = $mail_account['ssltype'] ?? ''; $mail_user = $mail_account['user'] ?? ''; @@ -223,7 +223,7 @@ class Connectors extends BaseSettings '$mail_pass' => ['mail_pass', $this->t('Email password:'), '', ''], '$mail_replyto' => ['mail_replyto', $this->t('Reply-to address:'), $mail_replyto, 'Optional'], '$mail_pubmail' => ['mail_pubmail', $this->t('Send public posts to all email contacts:'), $mail_pubmail, ''], - '$mail_action' => ['mail_action', $this->t('Action after import:'), $mail_action, '', [0 => $this->t('None'), 1 => $this->t('Delete'), 2 => $this->t('Mark as seen'), 3 => $this->t('Move to folder')]], + '$mail_action' => ['mail_action', $this->t('Action after import:'), $mail_action, '', [0 => $this->t('None'), 1 => $this->t('Delete'), 2 => $this->t('Mark as read'), 3 => $this->t('Move to folder')]], '$mail_movetofolder' => ['mail_movetofolder', $this->t('Move to folder:'), $mail_movetofolder, ''], '$submit' => $this->t('Save Settings'), ]); diff --git a/src/Module/Settings/Display.php b/src/Module/Settings/Display.php index 12da8f79eb..183e84c0f6 100644 --- a/src/Module/Settings/Display.php +++ b/src/Module/Settings/Display.php @@ -32,6 +32,7 @@ use Friendica\Module\Response; use Friendica\Navigation\SystemMessages; use Friendica\Network\HTTPException; use Friendica\Util\Profiler; +use Friendica\Util\Strings; use Psr\Log\LoggerInterface; /** @@ -106,6 +107,10 @@ class Display extends BaseSettings $update_content = (int)$request['update_content']; $embed_remote_media = (bool)$request['embed_remote_media']; $embed_media = (bool)$request['embed_media']; + $widget_timelineorder = trim($request['widget_timelineorder']); + $menu_timelineorder = trim($request['menu_timelineorder']); + $widget_timeline_reset = (bool)$request['widget_timeline_reset']; + $menu_timeline_reset = (bool)$request['menu_timeline_reset']; $enabled_timelines = []; foreach ($enable as $code => $enabled) { @@ -152,7 +157,16 @@ class Display extends BaseSettings $this->pConfig->set($uid, 'system', 'preview_mode', $preview_mode); $this->pConfig->set($uid, 'system', 'embed_remote_media', $embed_remote_media); $this->pConfig->set($uid, 'system', 'embed_media', $embed_media); - + if ($widget_timeline_reset) { + $this->pConfig->delete($uid, 'system', 'widget_timeline_order'); + } else { + $this->pConfig->set($uid, 'system', 'widget_timeline_order', $widget_timelineorder); + } + if ($menu_timeline_reset) { + $this->pConfig->delete($uid, 'system', 'menu_timeline_order'); + } else { + $this->pConfig->set($uid, 'system', 'menu_timeline_order', $menu_timelineorder); + } $this->pConfig->set($uid, 'system', 'network_timelines', $network_timelines); $this->pConfig->set($uid, 'system', 'enabled_timelines', $enabled_timelines); $this->pConfig->set($uid, 'channel', 'languages', $channel_languages); @@ -259,12 +273,13 @@ class Display extends BaseSettings ContactSelector::SVG_WHITE => $this->t('White'), ]; - $preview_mode = $this->pConfig->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_LARGE); + $preview_mode = $this->pConfig->get($uid, 'system', 'preview_mode', BBCode::PREVIEW_AUTO); $preview_modes = [ BBCode::PREVIEW_NONE => $this->t('No preview'), BBCode::PREVIEW_NO_IMAGE => $this->t('No image'), BBCode::PREVIEW_SMALL => $this->t('Small Image'), BBCode::PREVIEW_LARGE => $this->t('Large Image'), + BBCode::PREVIEW_AUTO => $this->t('Automatic image size'), ]; $bookmarked_timelines = $this->pConfig->get($uid, 'system', 'network_timelines', $this->getAvailableTimelines($uid, true)->column('code')); @@ -275,12 +290,77 @@ class Display extends BaseSettings $timelines = []; foreach ($this->getAvailableTimelines($uid) as $timeline) { $timelines[] = [ - 'label' => $timeline->label, - 'description' => $timeline->description, - 'enable' => ["enable[{$timeline->code}]", '', in_array($timeline->code, $enabled_timelines)], - 'bookmark' => ["bookmark[{$timeline->code}]", '', in_array($timeline->code, $bookmarked_timelines)], + 'enable' => ["enable[{$timeline->code}]", $timeline->label, in_array($timeline->code, $enabled_timelines), $timeline->description], + 'bookmark' => ["bookmark[{$timeline->code}]", $timeline->label, in_array($timeline->code, $bookmarked_timelines), $timeline->description], ]; } + /* GET CUSTOM TIMELINE ORDERS IF ANY + ================================= + First we see if there is a custom order saved in user prefs, if there is we set working array to that. + If we have an array create a temporary array with the items in the correct order. + Lastly we modify the $timelines array with our new order for "enable", "bookmark", or both. + */ + $widget_timeline_order = json_decode($this->pConfig->get($uid, 'system', 'widget_timeline_order')); + $menu_timeline_order = json_decode($this->pConfig->get($uid, 'system', 'menu_timeline_order')); + $temp_widget_order = []; + $temp_menu_order = []; + // do the sidebar widget order first... + if (!empty($widget_timeline_order)) { + $tmp = []; + $xtr = []; + foreach ($widget_timeline_order as $order) { + foreach ($timelines as $timeline) { + $name = str_replace(['enable[',']'], '', $timeline['enable'][0]); + if ($name == $order) { + $tmp[]['enable'] = $timeline['enable']; + } + } + } + // there could be custom or add-on channels not in our array, append those + foreach ($timelines as $timeline) { + $name = str_replace(['enable[',']'], '', $timeline['enable'][0]); + if (!in_array($name, $widget_timeline_order)) { + $xtr[]['enable'] = $timeline['enable']; + } + } + // combine our two temp arrays into one big temp array + $temp_widget_order = array_merge($tmp, $xtr); + } + // do the top menu order next... + if (!empty($menu_timeline_order)) { + $tmp = []; + $xtr = []; + foreach ($menu_timeline_order as $order) { + foreach ($timelines as $timeline) { + $name = str_replace(['bookmark[',']'], '', $timeline['bookmark'][0]); + if ($name == $order) { + $tmp[]['bookmark'] = $timeline['bookmark']; + } + } + } + // there could be custom or add-on channels unaccounted for in our array, append them + foreach ($timelines as $timeline) { + $name = str_replace(['bookmark[',']'], '', $timeline['bookmark'][0]); + if (!in_array($name, $menu_timeline_order)) { + $xtr[]['bookmark'] = $timeline['bookmark']; + } + } + // combine our two temp arrays into one big temp array + $temp_menu_order = array_merge($tmp, $xtr); + } + /* now we need to alter the original timelines array directly... + in theory populated temp arrays should be same length as timelines + */ + for ($t = 0; $t < count($timelines);$t++) { + // only mod from populated widget array + if (count($temp_widget_order) > 0) { + $timelines[$t]['enable'] = $temp_widget_order[$t]['enable']; + } + // only mod from populated menu array + if (count($temp_menu_order) > 0) { + $timelines[$t]['bookmark'] = $temp_menu_order[$t]['bookmark']; + } + } $first_day_of_week = $this->pConfig->get($uid, 'calendar', 'first_day_of_week', 0); $weekdays = [ @@ -309,21 +389,31 @@ class Display extends BaseSettings $tpl = Renderer::getMarkupTemplate('settings/display.tpl'); return Renderer::replaceMacros($tpl, [ - '$ptitle' => $this->t('Display Settings'), - '$submit' => $this->t('Save Settings'), - '$d_tset' => $this->t('General Theme Settings'), - '$d_ctset' => $this->t('Custom Theme Settings'), - '$d_cset' => $this->t('Content Settings'), - '$stitle' => $this->t('Theme settings'), - '$timeline_title' => $this->t('Timelines'), - '$channel_title' => $this->t('Channels'), - '$calendar_title' => $this->t('Calendar'), + '$ptitle' => $this->t('Display Settings'), + '$submit' => $this->t('Save Settings'), + '$d_cset' => $this->t('Content Settings'), + '$stitle' => $this->t('Theme settings'), + '$themes_title' => $this->t('Themes'), + '$themes_settings_for' => $this->t('Settings for %s', Strings::ucFirst($theme_selected)), + '$theme_changed_text' => $this->t('Note: If you switch the theme, you need to save changes before you can see the settings for the new theme below.'), + '$timeline_title' => $this->t('Timelines'), + '$channel_title' => $this->t('Channels'), + '$calendar_title' => $this->t('Calendar'), + '$sortable' => $this->t('Drag to reorder or tab to item with keyboard and move up/down with arrow keys'), + '$reset_widget' => [ + '0' => 'widget_timeline_reset', + '1' => $this->t('Reset order') + ], + '$reset_menu' => [ + '0' => 'menu_timeline_reset', + '1' => $this->t('Reset order') + ], '$form_security_token' => self::getFormSecurityToken('settings_display'), '$uid' => $uid, - '$theme' => ['theme', $this->t('Display Theme:'), $theme_selected, '', $themes, true], - '$mobile_theme' => ['mobile_theme', $this->t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, false], + '$theme' => ['theme', $this->t('Display theme'), $theme_selected, '', $themes, true], + '$mobile_theme' => ['mobile_theme', $this->t('Mobile theme'), $mobile_theme_selected, '', $mobile_themes, false], '$theme_config' => $theme_config, '$itemspage_network' => ['itemspage_network', $this->t('Number of items to display per page:'), $itemspage_network, $this->t('Maximum of 100 items')], @@ -346,8 +436,8 @@ class Display extends BaseSettings '$timeline_label' => $this->t('Label'), '$timeline_descriptiom' => $this->t('Description'), - '$timeline_enable' => $this->t('Enable'), - '$timeline_bookmark' => $this->t('Bookmark'), + '$timeline_enable' => $this->t('Channels Widget'), + '$timeline_bookmark' => $this->t('Top Menu'), '$timelines' => $timelines, '$timeline_explanation' => $this->t('Enable timelines that you want to see in the channels widget. Bookmark timelines that you want to see in the top menu.'), diff --git a/src/Module/Settings/Features.php b/src/Module/Settings/Features.php index 3c8d6ba5df..6cc388428e 100644 --- a/src/Module/Settings/Features.php +++ b/src/Module/Settings/Features.php @@ -8,6 +8,7 @@ namespace Friendica\Module\Settings; use Friendica\App; +use Friendica\Content\Conversation; use Friendica\Content\Feature; use Friendica\Core\L10n; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; @@ -35,7 +36,14 @@ class Features extends BaseSettings BaseSettings::checkFormSecurityTokenRedirectOnError('/settings/features', 'settings_features'); foreach ($request as $k => $v) { if (strpos($k, 'feature_') === 0) { - $this->pConfig->set($this->session->getLocalUserId(), 'feature', substr($k, 8), (bool)$v); + $key = substr($k, 8); + if ($key == 'widgetorder') { // not boolean, stringified array + $this->pConfig->set($this->session->getLocalUserId(), 'feature', 'widgetorder', $v); + } elseif ($key == 'resetorder' && $v) { + $this->pConfig->delete($this->session->getLocalUserId(), 'feature', 'widgetorder'); + } else { + $this->pConfig->set($this->session->getLocalUserId(), 'feature', $key, $v); + } } } } @@ -52,13 +60,34 @@ class Features extends BaseSettings $arr[$name][1][] = ['feature_' . $f[0], $f[1], Feature::isEnabled($this->session->getLocalUserId(), $f[0]), $f[2]]; } } + // try to get widget order preference + $widgetorder = json_decode($this->pConfig->get($this->session->getLocalUserId(), 'feature', 'widgetorder')); + if (!empty($widgetorder)) { + $tmp = []; + // iterate through widgetorder and network items + foreach ($widgetorder as $widget) { + foreach ($arr['network'][1] as $list_item) { + if ($list_item[0] == 'feature_'.$widget) { + $tmp[] = $list_item; + } + } + } + // replace network order with temp array order + $arr['network'][1] = $tmp; + }; $tpl = Renderer::getMarkupTemplate('settings/features.tpl'); return Renderer::replaceMacros($tpl, [ '$form_security_token' => BaseSettings::getFormSecurityToken('settings_features'), '$title' => $this->t('Additional Features'), - '$features' => $arr, - '$submit' => $this->t('Save Settings'), + '$sortable' => $this->t('Drag to reorder or tab to item with keyboard and move up/down with arrow keys'), + '$network_mode' => Conversation::MODE_NETWORK, + '$reset' => [ + '0' => 'feature_resetorder', + '1' => $this->t('Reset order') + ], + '$features' => $arr, + '$submit' => $this->t('Save Settings'), ]); } } diff --git a/src/Network/HTTPClient/Client/HttpClientAccept.php b/src/Network/HTTPClient/Client/HttpClientAccept.php index 2432633032..743ceb2fe2 100644 --- a/src/Network/HTTPClient/Client/HttpClientAccept.php +++ b/src/Network/HTTPClient/Client/HttpClientAccept.php @@ -32,4 +32,5 @@ class HttpClientAccept public const VIDEO = 'video/mp4,video/*;q=0.9,*/*;q=0.8'; public const XRD_XML = 'application/xrd+xml,text/xml;q=0.9,*/*;q=0.8'; public const XML = 'application/xml,text/xml;q=0.9,*/*;q=0.8'; + public const HLS = 'application/vnd.apple.mpegurl,application/x-mpegURL;q=0.9,*/*;q=0.8'; } diff --git a/src/Object/Post.php b/src/Object/Post.php index 390a466c0b..1a4e1f57de 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -216,6 +216,10 @@ class Post $announceable = false; } + if ($item['restrictions'] & Item::CANT_QUOTE) { + $shareable = false; + } + $edpost = false; if (DI::userSession()->getLocalUserId()) { diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 405d230341..69b4eaa022 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -50,15 +50,38 @@ class ActivityPub const CONTEXT = [ 'https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1', [ - 'ostatus' => 'http://ostatus.org#', - 'vcard' => 'http://www.w3.org/2006/vcard/ns#', - 'dfrn' => 'http://purl.org/macgirvin/dfrn/1.0/', - 'diaspora' => 'https://diasporafoundation.org/ns/', - 'litepub' => 'http://litepub.social/ns#', - 'toot' => 'http://joinmastodon.org/ns#', + 'ostatus' => 'http://ostatus.org#', + 'vcard' => 'http://www.w3.org/2006/vcard/ns#', + 'dfrn' => 'http://purl.org/macgirvin/dfrn/1.0/', + 'diaspora' => 'https://diasporafoundation.org/ns/', + 'litepub' => 'http://litepub.social/ns#', + 'toot' => 'http://joinmastodon.org/ns#', + 'quote' => 'https://w3id.org/fep/044f#quote', + 'quoteUri' => 'http://fedibird.com/ns#quoteUri', + 'quoteAuthorization' => [ + '@id' => 'https://w3id.org/fep/044f#quoteAuthorization', + '@type' => '@id', + ], + 'gts' => 'https://gotosocial.org/ns#', + 'interactionPolicy' => [ + '@id' => 'gts:interactionPolicy', + '@type' => '@id', + ], + 'canQuote' => [ + '@id' => 'gts:canQuote', + '@type' => '@id', + ], + 'automaticApproval' => [ + '@id' => 'gts:automaticApproval', + '@type' => '@id', + ], + 'manualApproval' => [ + '@id' => 'gts:manualApproval', + '@type' => '@id', + ], 'featured' => [ - "@id" => "toot:featured", - "@type" => "@id", + "@id" => 'toot:featured', + "@type" => '@id', ], 'schema' => 'http://schema.org#', 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', @@ -191,10 +214,11 @@ class ActivityPub * * @param string $url * @param integer $uid User ID + * @param integer $max Maximum number of activities to fetch (0 = all) * @return void * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function fetchOutbox(string $url, int $uid) + public static function fetchOutbox(string $url, int $uid, int $max = 0) { $data = HTTPSignature::fetch($url, $uid); if (empty($data)) { @@ -212,9 +236,14 @@ class ActivityPub $items = []; } + $count = 0; foreach ($items as $activity) { $ldactivity = JsonLD::compact($activity); ActivityPub\Receiver::processActivity($ldactivity, '', $uid, true); + if ($max > 0 && ++$count >= $max) { + DI::logger()->info('Reached maximum number of activities to fetch', ['url' => $url, 'uid' => $uid, 'max' => $max]); + return; + } } } @@ -250,6 +279,8 @@ class ActivityPub $items = $data['first']['items']; } elseif (!empty($data['first']) && is_string($data['first']) && ($data['first'] != $url)) { return self::fetchItems($data['first'], $uid, $start_timestamp); + } elseif (isset($data['first']) && isset($data['first']['next']) && ($data['first']['next'] != $url)) { + return self::fetchItems($data['first']['next'], $uid, $start_timestamp); } else { return []; } diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index e714a1d9c1..e9a721b5db 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -46,6 +46,11 @@ class Processor const CACHEKEY_FETCH_ACTIVITY = 'processor:fetchMissingActivity:'; const CACHEKEY_JUST_FETCHED = 'processor:isJustFetched:'; + const FETCH_REPLIES_ALL = 0; + const FETCH_REPLIES_NONE = 1; + const FETCH_REPLIES_FOLLOWED = 2; + const FETCH_REPLIES_INTERACTION = 3; + /** * Add an object id to the list of processed ids * @@ -158,6 +163,10 @@ class Processor $data['player-url'] = $attachment['player-url'] ?? null; $data['player-height'] = $attachment['player-height'] ?? null; $data['player-width'] = $attachment['player-width'] ?? null; + $data['embed-type'] = $attachment['embed-type'] ?? null; + $data['embed-html'] = $attachment['embed-html'] ?? null; + $data['embed-width'] = $attachment['embed-width'] ?? null; + $data['embed-height'] = $attachment['embed-height'] ?? null; Post\Media::insert($data); } @@ -256,7 +265,62 @@ class Processor self::updateEvent($post['event-id'], $activity); } } - self::processReplies($activity, $item); + + if (self::shouldCompleteThread($item)) { + if (Worker::isInWorkerMode()) { + self::processReplies($activity, $item); + } else { + Worker::add(Worker::PRIORITY_MEDIUM, 'FetchMissingReplies', $item['uri-id'], $activity); + } + } + } + + private static function shouldCompleteThread(array $item): bool + { + switch (DI::config()->get('system', 'fetch_replies')) { + case self::FETCH_REPLIES_ALL: + DI::logger()->debug('Fetch all replies is enabled'); + return true; + + case self::FETCH_REPLIES_FOLLOWED: + DI::logger()->debug('Fetch replies from followed users is enabled'); + return Post::exists(["`parent-uri-id` = ? AND `gravity` IN (?, ?) AND `uid` != ?", $item['parent-uri-id'], Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT, 0]); + + case self::FETCH_REPLIES_INTERACTION: + DI::logger()->debug('Fetch replies with interaction is enabled'); + return Post::exists(["`parent-uri-id` = ? AND `origin`", $item['parent-uri-id']]); + } + + DI::logger()->debug('No reply fetching is enabled'); + return false; + } + + /** + * Fetch replies for a given uri id + * + * @param int $uriId Uri-id of the parent item + * @param array $child Child activity data + */ + public static function fetchRepliesByUriId(int $uriId, array $child = []) + { + $item = Post::selectFirstPost(['thr-parent', 'parent-uri', 'replies'], ['uri-id' => $uriId, 'private' => [Item::PUBLIC, Item::UNLISTED]]); + if (!$item) { + return; + } + + if (!$child) { + $activity = DBA::selectFirst('post-activity', [], ['uri-id' => $uriId]); + $data = json_decode($activity['activity'] ?? '', true); + if ($data) { + $activity = JsonLD::compact($data); + + $trust_source = true; + $child = Receiver::prepareObjectData($activity, 0, false, $trust_source); + } + } + + DI::logger()->debug('Process replies', ['uri-id' => $uriId, 'replies' => !$item['replies']]); + self::processReplies($child, $item); } /** @@ -516,29 +580,28 @@ class Processor private static function processReplies(array $activity, array $item) { - // @todo fetch replies not only in the decoupled mode - if (!DI::config()->get('system', 'decoupled_receiver')) { + if (isset($item['parent-uri-id'])) { + $condition = ['parent-uri-id' => $item['parent-uri-id']]; + } elseif (isset($item['thr-parent-id'])) { + $parent = Post::selectFirstPost(['parent-uri-id'], ['uri-id' => $item['thr-parent-id']]); + if (isset($parent['parent-uri-id'])) { + $condition = ['parent-uri-id' => $parent['parent-uri-id']]; + } else { + $condition = ['uri-id' => [$item['thr-parent-id'], $item['uri-id']]]; + } + } elseif (isset($item['replies'])) { + self::fetchReplies($item['replies'], $activity); + return; + } else { return; } - $replies = [$item['thr-parent']]; - if (!empty($item['parent-uri'])) { - $replies[] = $item['parent-uri']; - } - $condition = DBA::mergeConditions(['uri' => $replies], ["`replies-id` IS NOT NULL"]); + $condition = DBA::mergeConditions($condition, ["`replies-id` IS NOT NULL"]); $posts = Post::select(['replies', 'replies-id'], $condition); while ($post = Post::fetch($posts)) { - $cachekey = 'Processor-CreateItem-Replies-' . $post['replies-id']; - if (!DI::cache()->get($cachekey)) { - self::fetchReplies($post['replies'], $activity); - DI::cache()->set($cachekey, true); - } - } - DBA::close($replies); - - if (!empty($item['replies'])) { - self::fetchReplies($item['replies'], $activity); + self::fetchReplies($post['replies'], $activity); } + DBA::close($posts); } /** @@ -960,30 +1023,10 @@ class Processor self::storeReceivers($item['uri-id'], $activity['receiver_urls'] ?? []); - if (!empty($activity['capabilities'])) { - $restrictions = self::storeCapabilities($item['uri-id'], $activity['capabilities']); - } elseif (!is_null($activity['can-comment']) && !$activity['can-comment']) { - $restrictions = [Tag::CAN_REPLY]; - } else { - $restrictions = []; - } - - $item['restrictions'] = null; - foreach ($restrictions as $restriction) { - if ($restriction == Tag::CAN_REPLY) { - $item['restrictions'] = $item['restrictions'] | Item::CANT_REPLY; - } elseif ($restriction == Tag::CAN_LIKE) { - $item['restrictions'] = $item['restrictions'] | Item::CANT_LIKE; - } elseif ($restriction == Tag::CAN_ANNOUNCE) { - $item['restrictions'] = $item['restrictions'] | Item::CANT_ANNOUNCE; - } - } - - if (!empty($item['author-id'])) { - $author = Contact::selectFirstAccount(['ap-posting-restricted'], ['id' => $item['author-id']]); - if (!empty($author['ap-posting-restricted'])) { - $item['restrictions'] = $item['restrictions'] | Item::CANT_REPLY; - } + if (!empty($activity['interaction'])) { + self::storeInteractions($item['uri-id'], $activity['interaction']); + } elseif (!empty($activity['capabilities'])) { + self::storeCapabilities($item['uri-id'], $activity['capabilities'], $item['author-id']); } $item['location'] = $activity['location']; @@ -1262,8 +1305,12 @@ class Processor } } - if ($success) { - self::processReplies($activity, $item); + if ($success && self::shouldCompleteThread($item)) { + if (Worker::isInWorkerMode()) { + self::processReplies($activity, $item); + } else { + Worker::add(Worker::PRIORITY_MEDIUM, 'FetchMissingReplies', $item['uri-id'], $activity); + } } } @@ -1355,7 +1402,7 @@ class Processor * @param integer $uriid * @param array $tags */ - private static function storeTags(int $uriid, array $tags = null) + private static function storeTags(int $uriid, ?array $tags = null) { foreach ($tags as $tag) { if (empty($tag['name']) || empty($tag['type']) || !in_array($tag['type'], ['Mention', 'Hashtag'])) { @@ -1416,16 +1463,90 @@ class Processor } } - private static function storeCapabilities(int $uriid, array $capabilities): array + public static function getRestrictions(int $uriid, int $author_id, int $uid): ?int + { + $author = Contact::getAccountById($author_id, ['ap-following', 'ap-followers', 'ap-posting-restricted']); + if ($author['ap-posting-restricted']) { + return Item::CANT_REPLY; + } + + $tags = Tag::getByURIId($uriid, [Tag::CAN_ANNOUNCE, Tag::CAN_LIKE, Tag::CAN_REPLY, Tag::CAN_QUOTE]); + if (!is_array($tags) || sizeof($tags) == 0) { + return null; + } + + $restrictions = 0; + foreach ($tags as $tag) { + if ($tag['url'] == ActivityPub::PUBLIC_COLLECTION) { + continue; + } + + if ($uid != 0) { + if (User::getIdForURL($tag['url']) == $uid) { + continue; + } + if ($tag['url'] == $author['ap-following'] && Contact::isSharing($author_id, $uid, true)) { + continue; + } + if ($tag['url'] == $author['ap-followers'] && Contact::isFollower($author_id, $uid, true)) { + continue; + } + } + if ($tag['type'] == Tag::CAN_REPLY) { + $restrictions = $restrictions | Item::CANT_REPLY; + } elseif ($tag['type'] == Tag::CAN_LIKE) { + $restrictions = $restrictions | Item::CANT_LIKE; + } elseif ($tag['type'] == Tag::CAN_ANNOUNCE) { + $restrictions = $restrictions | Item::CANT_ANNOUNCE; + } elseif ($tag['type'] == Tag::CAN_QUOTE) { + $restrictions = $restrictions | Item::CANT_QUOTE; + } + } + DI::logger()->debug('Calculated restrictions', ['uri-id' => $uriid, 'author-id' => $author_id, 'uid' => $uid, 'restrictions' => $restrictions]); + return $restrictions; + } + + private static function storeInteractions(int $uriid, array $interactions) + { + foreach ($interactions as $key => $key_interaction) { + foreach ($key_interaction as $interaction) { + if ($interaction == ActivityPub::PUBLIC_COLLECTION) { + $name = Receiver::PUBLIC_COLLECTION; + } elseif ($path = parse_url($interaction, PHP_URL_PATH)) { + $name = trim($path, '/'); + } elseif ($host = parse_url($interaction, PHP_URL_HOST)) { + $name = $host; + } else { + DI::logger()->warning('Unable to coerce name from interaction', ['key' => $key, 'interaction' => $interaction]); + $name = ''; + } + DI::logger()->debug('Storing interaction', ['uri-id' => $uriid, 'key' => $key, 'name' => $name, 'interaction' => $interaction]); + Tag::store($uriid, $key, $name, $interaction); + } + } + } + + private static function storeCapabilities(int $uriid, array $capabilities, int $author_id) { - $restrictions = []; foreach (['pixelfed:canAnnounce' => Tag::CAN_ANNOUNCE, 'pixelfed:canLike' => Tag::CAN_LIKE, 'pixelfed:canReply' => Tag::CAN_REPLY] as $element => $type) { - $restricted = true; + if (!isset($capabilities[$element])) { + $author = Contact::getAccountById($author_id, ['nick', 'url']); + if (!$author) { + continue; + } + Tag::store($uriid, $type, $author['nick'] ?: $author['url'], $author['url']); + continue; + } foreach ($capabilities[$element] ?? [] as $capability) { if ($capability == ActivityPub::PUBLIC_COLLECTION) { $name = Receiver::PUBLIC_COLLECTION; } elseif (empty($capability) || ($capability == '[]')) { - continue; + $author = Contact::getAccountById($author_id, ['nick', 'url']); + if (!$author) { + continue; + } + $name = $author['nick'] ?: $author['url']; + $capability = $author['url']; } elseif ($path = parse_url($capability, PHP_URL_PATH)) { $name = trim($path, '/'); } elseif ($host = parse_url($capability, PHP_URL_HOST)) { @@ -1434,14 +1555,9 @@ class Processor DI::logger()->warning('Unable to coerce name from capability', ['element' => $element, 'type' => $type, 'capability' => $capability]); $name = ''; } - $restricted = false; Tag::store($uriid, $type, $name, $capability); } - if ($restricted) { - $restrictions[] = $type; - } } - return $restrictions; } /** @@ -1797,6 +1913,16 @@ class Processor private static function fetchReplies(string $url, array $child) { + if (DI::baseUrl()->isLocalUrl($url)) { + return; + } + + if (self::isFetched($url)) { + DI::logger()->debug('Url is already processed', ['url' => $url]); + return; + } + self::addActivityId($url); + $callstack_count = 0; foreach ($child['callstack'] ?? [] as $function) { if ($function == __FUNCTION__) { @@ -1850,6 +1976,7 @@ class Processor $id = $reply; } if (!self::alreadyKnown($id, $child['id'] ?? '')) { + DI::logger()->debug('Fetch missing activity', ['url' => $url, 'id' => $id]); self::fetchMissingActivity($id, $child, '', Receiver::COMPLETION_REPLIES); ++$fetched; } @@ -2127,6 +2254,46 @@ class Processor Queue::remove($activity); } + /** + * process a "quote" request + * + * @param array $activity + * @return void + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function processQuoteRequest(array $activity) + { + if (!($post = Post::selectFirst(['author-link', 'uid'], ['uri' => $activity['object_id'], 'origin' => true, 'private' => [Item::PUBLIC, Item::UNLISTED]]))) { + DI::logger()->info('Quoted post not found locally or it is not public', ['uri' => $activity['object_id']]); + Queue::remove($activity); + return; + } + if (!($contact = Contact::getByURL($activity['actor'], null, ['url']))) { + DI::logger()->info('Actor is not a known contact', ['actor' => $activity['actor']]); + return; + } + + $owner = User::getOwnerDataById($post['uid']); + if (!DBA::isResult($owner)) { + return; + } + + $quote = Post::selectFirst(['guid'], ['uri' => $activity['target_id']]); + if (!isset($quote['guid'])) { + if (Processor::fetchMissingActivity($activity['target_id'], $activity, '', Receiver::COMPLETION_ANNOUNCE)) { + $quote = Post::selectFirst(['guid'], ['uri' => $activity['target_id']]); + } + } + if (!isset($quote['guid'])) { + DI::logger()->debug('Remote quote was not found', ['uri' => $activity['target_id']]); + return; + } + + ActivityPub\Transmitter::acceptQuoteRequest($contact['url'], $activity['target_id'], $quote['guid'], $post['author-link'], $activity['object_id'], $activity['id'], $owner); + Queue::remove($activity); + } + /** * Transmit pending events to the new follower * diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 399d74cd63..a807a74955 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -20,6 +20,7 @@ use Friendica\Model\Contact; use Friendica\Model\APContact; use Friendica\Model\Item; use Friendica\Model\Post; +use Friendica\Model\Tag; use Friendica\Model\User; use Friendica\Protocol\Activity; use Friendica\Protocol\ActivityPub; @@ -453,6 +454,13 @@ class Receiver $object_data['object_id'] = JsonLD::fetchElement($activity, 'as:object', '@id'); $object_data['object_type'] = JsonLD::fetchElement($activity['as:object'], '@type'); $object_data['object_content'] = JsonLD::fetchElement($activity['as:object'], 'as:content', '@type'); + } elseif (in_array($type, ['quote:QuoteRequest'])) { + $object_data = []; + + $object_data['id'] = JsonLD::fetchElement($activity, '@id'); + $object_data['target_id'] = JsonLD::fetchElement($activity, 'as:instrument', '@id', '@type', 'as:Note'); + $object_data['object_id'] = JsonLD::fetchElement($activity, 'as:object', '@id'); + $object_data['object_type'] = JsonLD::fetchElement($activity['as:object'], '@type'); } else { $object_data = []; @@ -611,7 +619,7 @@ class Receiver * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function processActivity(array $activity, string $body = '', int $uid = null, bool $trust_source = false, bool $push = false, array $signer = [], string $http_signer = '', int $completion = Receiver::COMPLETION_AUTO): bool + public static function processActivity(array $activity, string $body = '', ?int $uid = null, bool $trust_source = false, bool $push = false, array $signer = [], string $http_signer = '', int $completion = Receiver::COMPLETION_AUTO): bool { $type = JsonLD::fetchElement($activity, '@type'); if (!$type) { @@ -1055,6 +1063,10 @@ class Receiver } break; + case 'quote:QuoteRequest': + ActivityPub\Processor::processQuoteRequest($object_data); + break; + default: DI::logger()->info('Unknown activity: ' . $type . ' ' . $object_data['object_type']); return false; @@ -1076,7 +1088,7 @@ class Receiver * @param array $signer The signer of the post * @return void */ - private static function storeUnhandledActivity(bool $unknown, string $type, array $object_data, array $activity, string $body = '', int $uid = null, bool $trust_source = false, bool $push = false, array $signer = []) + private static function storeUnhandledActivity(bool $unknown, string $type, array $object_data, array $activity, string $body = '', ?int $uid = null, bool $trust_source = false, bool $push = false, array $signer = []) { if (!DI::config()->get('debug', 'ap_log_unknown')) { return; @@ -1867,9 +1879,10 @@ class Receiver * @param array $urls The object URL list * @param string|null $icon The icon URL to use for the attachments * @param array $player Embedded player data (url, width, height) + * @param array $embed oEmbed data (html, width, height) * @return array an array of attachments */ - private static function processAttachmentUrls(array $urls, ?string $icon, array $player): array + private static function processAttachmentUrls(array $urls, ?string $icon, array $player, array $embed): array { $attachments = []; foreach ($urls as $key => $url) { @@ -1893,13 +1906,14 @@ class Receiver } $filetype = strtolower(substr($mediatype, 0, strpos($mediatype, '/'))); + $type = Post\Media::getType($mediatype); $height = JsonLD::fetchElement($url, 'as:height', '@value'); $width = JsonLD::fetchElement($url, 'as:width', '@value'); - if ($filetype == 'audio') { + if ($type == Post\Media::AUDIO) { $attachments[] = ['type' => $filetype, 'mediaType' => $mediatype, 'url' => $href, 'height' => $height, 'width' => $width, 'size' => null, 'name' => '', 'image' => $icon]; - } elseif ($filetype == 'video') { + } elseif ($type == Post\Media::VIDEO) { // PeerTube audio-only track if (!$height) { continue; @@ -1908,40 +1922,33 @@ class Receiver $size = (int)JsonLD::fetchElement($url, 'pt:size', '@value'); $attachments[] = ['type' => $filetype, 'mediaType' => $mediatype, 'url' => $href, 'height' => $height, 'width' => $width, 'size' => $size, 'name' => '', 'image' => $icon]; - } elseif (in_array($mediatype, ['application/x-bittorrent', 'application/x-bittorrent;x-scheme-handler/magnet'])) { + } elseif ($type == Post\Media::TORRENT) { // For Torrent links we always store the highest resolution if (!empty($attachments[$mediatype]['height']) && ($height < $attachments[$mediatype]['height'])) { continue; } $attachments[$mediatype] = ['type' => $mediatype, 'mediaType' => $mediatype, 'url' => $href, 'height' => $height, 'width' => $width, 'size' => null, 'name' => '']; - } elseif ($mediatype == 'application/x-mpegURL') { - // PeerTube uses HLS streams for video. We prefer HLS streams over the video file itself. - // But we still store the video file as an attachment to be used by the API which currently does not support HLS streams. - $attachments = array_merge($attachments, self::processAttachmentUrls($url['as:tag'], $icon, [])); - + } elseif ($type == Post\Media::HLS) { $attachment = ['type' => $filetype, 'mediaType' => $mediatype, 'url' => $href, 'height' => $height, 'width' => $width, 'size' => null, 'name' => '', 'image' => $icon]; - if (!empty($player)) { + if (is_array($player)) { $attachment['player-url'] = $player['embed'] ?? null; $attachment['player-height'] = $player['height'] ?? null; $attachment['player-width'] = $player['width'] ?? null; - if (is_null($attachment['player-height']) && is_null($attachment['player-width'])) { - foreach ($attachments as $media) { - if (isset($media['height']) && isset($media['width'])) { - if ($media['height'] > $attachment['player-height'] || $media['width'] > $attachment['player-width']) { - $attachment['player-height'] = $media['height']; - $attachment['player-width'] = $media['width']; - } - } - } - } - if (!$height && !$width) { $attachment['height'] = $attachment['player-height']; $attachment['width'] = $attachment['player-width']; } } + + if (is_array($embed)) { + $attachment['embed-type'] = $embed['type'] ?? null; + $attachment['embed-html'] = $embed['html'] ?? null; + $attachment['embed-height'] = $embed['height'] ?? null; + $attachment['embed-width'] = $embed['width'] ?? null; + } + DI::logger()->info('Adding video attachment', ['attachment' => $attachment]); $attachments[] = $attachment; } @@ -1986,6 +1993,10 @@ class Receiver } } + if (!empty($object['gts:interactionPolicy'])) { + $object_data['interaction'] = self::getinteractionPolicy($object['gts:interactionPolicy']); + } + if (!empty($object['pixelfed:capabilities'])) { $object_data['capabilities'] = self::getCapabilities($object); } @@ -1993,6 +2004,34 @@ class Receiver return $object_data; } + /** + * Import GoToSocial's interaction policx + * @see https://docs.gotosocial.org/en/latest/federation/interaction_policy/ + * + * @param array $object + * @return array + */ + private static function getinteractionPolicy(array $object): array + { + $interactions = []; + foreach ([Tag::CAN_ANNOUNCE => 'gts:canAnnounce', Tag::CAN_LIKE => 'gts:canLike', Tag::CAN_REPLY => 'gts:canReply', Tag::CAN_QUOTE => 'gts:canQuote'] as $key => $element) { + foreach (['gts:automaticApproval', 'gts:manualApproval'] as $approval) { + if (!isset($object[$element][$approval])) { + continue; + } + $interaction = JsonLD::fetchElement($object[$element][$approval], '@id'); + if (empty($interaction)) { + continue; + } + if ($interaction == self::PUBLIC_COLLECTION) { + $interaction = ActivityPub::PUBLIC_COLLECTION; + } + $interactions[$key][] = $interaction; + } + } + return $interactions; + } + private static function getCapabilities($object) { $capabilities = []; @@ -2001,7 +2040,13 @@ class Receiver if (empty($capabilities_list)) { continue; } - $capabilities[$element] = $capabilities_list; + + foreach ($capabilities_list as $capability) { + if ($capability == self::PUBLIC_COLLECTION) { + $capability = ActivityPub::PUBLIC_COLLECTION; + } + $capabilities[$element][] = $capability; + } } return $capabilities; } @@ -2130,13 +2175,13 @@ class Receiver } else { $player = []; } + if (isset($siteinfo['embed'])) { + $embed = $siteinfo['embed']; + } else { + $embed = []; + } - $object_data['attachments'] = array_merge($object_data['attachments'], self::processAttachmentUrls($object['as:url'] ?? [], self::processIcon($object), $player)); - } - - $object_data['can-comment'] = JsonLD::fetchElement($object, 'pt:commentsEnabled', '@value'); - if (is_null($object_data['can-comment'])) { - $object_data['can-comment'] = JsonLD::fetchElement($object, 'pixelfed:commentsEnabled', '@value'); + $object_data['attachments'] = array_merge($object_data['attachments'], self::processAttachmentUrls($object['as:url'] ?? [], self::processIcon($object), $player, $embed)); } // Support for quoted posts (Pleroma, Fedibird and Misskey) @@ -2153,6 +2198,13 @@ class Receiver if (empty($object_data['quote-url'])) { $object_data['quote-url'] = JsonLD::fetchElement($object, 'misskey:_misskey_quote', '@id'); } + if (empty($object_data['quote-url'])) { + $object_data['quote-url'] = JsonLD::fetchElement($object, 'quote:quote'); + } + + if (!is_null($object_data['quote-url']) && !is_null($object_data['content'])) { + $object_data['content'] = HTML::removeElementByClass($object_data['content'], 'quote-inline'); + } foreach ($object_data['tags'] as $tag) { if (HTTPSignature::isValidContentType($tag['mediaType'] ?? '', $tag['href'] ?? '')) { diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 65b45bb3ea..bbfd52e0e4 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -1527,9 +1527,9 @@ class Transmitter * * @param array $tags Tag array * @param string $text Text containing tags like :tag: - * @return string normalized text + * @return string|null normalized text or null */ - private static function addEmojiTags(array &$tags, string $text): string + private static function addEmojiTags(array &$tags, string $text): ?string { $emojis = Smilies::extractUsedSmilies($text, $normalized); foreach ($emojis as $name => $url) { @@ -1899,6 +1899,7 @@ class Transmitter $real_quote = true; $data['_misskey_content'] = BBCode::removeSharedData($body); $data['quoteUrl'] = $item['quote-uri']; + $data['quoteUri'] = $item['quote-uri']; $body = DI::contentItem()->addShareLink($body, $item['quote-uri-id']); } else { $body = DI::contentItem()->addSharedPost($item, $body); @@ -1925,6 +1926,10 @@ class Transmitter $richbody = BBCode::replaceAttachment($richbody); $data['contentMap'][$language] = BBCode::convertForUriId($item['uri-id'], $richbody, BBCode::EXTERNAL); + + if ($data['content'] == '') { + $data['content'] = $data['contentMap'][$language]; + } } if (!empty($item['quote-uri-id']) && ($item['quote-uri-id'] != $item['uri-id'])) { @@ -1939,9 +1944,25 @@ class Transmitter $data['diaspora:comment'] = $item['signed_text']; } + // @todo full support of GoToSocial's interaction policy + // @see https://docs.gotosocial.org/en/latest/federation/interaction_policy/ + if ($item['private'] != Item::PRIVATE) { + $data['interactionPolicy'] = [ + 'canQuote' => [ + 'automaticApproval' => [ActivityPub::PUBLIC_COLLECTION] + ] + ]; + } + $data['attachment'] = self::createAttachmentList($item); $data['tag'] = array_merge(self::createTagList($item, $data['quoteUrl'] ?? ''), $emojis); + $data['replies'] = [ + 'id' => $item['uri'] . '/replies', + 'type' => 'Collection', + 'totalItems' => Post::countPosts(['thr-parent-id' => $item['uri-id'], 'gravity' => Item::GRAVITY_COMMENT, 'deleted' => false, 'private' => [Item::PUBLIC, Item::UNLISTED]]) + ]; + if (empty($data['location']) && (!empty($item['coord']) || !empty($item['location']))) { $data['location'] = self::createLocation($item); } @@ -2516,6 +2537,54 @@ class Transmitter return HTTPSignature::transmit($signed, $profile['inbox'], $owner); } + /** + * Accepts a quote request + * + * @param string $remote_actor Remote actor URL + * @param string $remote_quote_id Remote quote ID + * @param string $remote_quote_guid Remote quote guid + * @param string $local_actor Local actor URL + * @param string $local_quote_id Local quote ID + * @param string $request_id Quote request ID + * @param array $owner Sender owner-view record + * @return bool success + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + * @throws \Exception + */ + public static function acceptQuoteRequest(string $remote_actor, string $remote_quote_id, string $remote_quote_guid, string $local_actor, string $local_quote_id, string $request_id, array $owner): bool + { + $profile = APContact::getByURL($remote_actor); + if (empty($profile['inbox'])) { + DI::logger()->warning('No inbox found for target', ['target' => $remote_actor, 'profile' => $profile]); + return false; + } + + $objectId = DI::baseUrl() . '/activity/' . System::createGUID(); + + $data = [ + '@context' => ActivityPub::CONTEXT, + 'type' => 'Accept', + 'to' => $remote_actor, + 'id' => $objectId, + 'actor' => $local_actor, + 'object' => [ + 'type' => 'QuoteRequest', + 'id' => $request_id, + 'actor' => $remote_actor, + 'object' => $local_quote_id, + 'instrument' => $remote_quote_id, + ], + 'result' => $local_quote_id . '/quote_authorization/' . $remote_quote_guid, + 'instrument' => self::getService(), + ]; + + DI::logger()->info('Accept quote request', ['id' => $request_id, 'quote-id' => $local_quote_id, 'remote-id' => $remote_quote_id, 'actor' => $remote_actor, 'data' => $data]); + + $signed = LDSignature::sign($data, $owner); + return HTTPSignature::transmit($signed, $profile['inbox'], $owner); + } + /** * Prepends mentions (@) to $body variable * diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index 48780e6181..7fc87085a3 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -279,8 +279,7 @@ class Feed return []; } - $items = []; - $creation_dates = []; + $items = []; // Limit the number of items that are about to be fetched $total_items = ($entries->length - 1); @@ -289,7 +288,10 @@ class Feed $total_items = $max_items; } - $postings = self::importOlderEntries($entries, $total_items, $header, $author, $contact, $importer, $xpath, $atomns, $basepath, $dryRun); + $processed = self::processEntries($entries, $total_items, $header, $author, $contact, $importer, $xpath, $atomns, $basepath, $dryRun); + + $postings = $processed['postings']; + $creation_dates = $processed['creation_dates']; if (!empty($postings)) { $min_posting = DI::config()->get('system', 'minimum_posting_interval', 0); @@ -358,9 +360,10 @@ class Feed return $title; } - private static function importOlderEntries(DOMNodeList $entries, int $total_items, array $header, array $author, array $contact, array $importer, DOMXPath $xpath, string $atomns, string $basepath, bool $dryRun): array + private static function processEntries(DOMNodeList $entries, int $total_items, array $header, array $author, array $contact, array $importer, DOMXPath $xpath, string $atomns, string $basepath, bool $dryRun): array { - $postings = []; + $postings = []; + $creation_dates = []; // Importing older entries first for ($i = $total_items; $i >= 0; --$i) { @@ -685,29 +688,6 @@ class Feed $taglist = $fetch_further_information == LocalRelationship::FFI_BOTH ? PageInfo::getTagsFromUrl($item['plink'], $preview, $contact['ffi_keyword_denylist'] ?? '') : []; $item['object-type'] = Activity\ObjectType::BOOKMARK; $attachments = []; - - foreach (['audio', 'video'] as $elementname) { - if (!empty($data[$elementname])) { - foreach ($data[$elementname] as $element) { - if (!empty($element['src'])) { - $src = $element['src']; - } elseif (!empty($element['content'])) { - $src = $element['content']; - } else { - continue; - } - - $attachments[] = [ - 'type' => ($elementname == 'audio') ? Post\Media::AUDIO : Post\Media::VIDEO, - 'url' => $src, - 'preview' => $element['image'] ?? null, - 'mimetype' => $element['contenttype'] ?? null, - 'name' => $element['name'] ?? null, - 'description' => $element['description'] ?? null, - ]; - } - } - } } } else { if ($fetch_further_information == LocalRelationship::FFI_KEYWORD) { @@ -762,7 +742,7 @@ class Feed } } - return $postings; + return ['postings' => $postings, 'creation_dates' => $creation_dates]; } /** diff --git a/src/Util/DateTimeFormat.php b/src/Util/DateTimeFormat.php index 830b50a2fe..af26317b46 100644 --- a/src/Util/DateTimeFormat.php +++ b/src/Util/DateTimeFormat.php @@ -121,6 +121,10 @@ class DateTimeFormat $s = 'now'; } + if (is_numeric($s) && ($s > time() * 100)) { + $s = number_format($s / 1000, 0, '.', ''); + } + // Lowest possible datetime value if (substr($s, 0, 10) <= '0001-01-01') { $d = new DateTime('now', new DateTimeZone('UTC')); diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index 676c944381..42c561a120 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -60,6 +60,12 @@ class JsonLD case 'https://purl.archive.org/socialweb/webfinger': $url = DI::basePath() . '/static/socialweb-webfinger.jsonld'; break; + case 'https://www.w3.org/ns/cid/v1': + $url = DI::basePath() . '/static/cid-v1.jsonld'; + break; + case 'https://w3id.org/security/data-integrity/v2': + $url = DI::basePath() . '/static/data-integrity-v2.jsonld'; + break; default: switch (parse_url($url, PHP_URL_PATH)) { case '/schemas/litepub-0.1.jsonld': @@ -165,6 +171,8 @@ class JsonLD 'misskey' => (object)['@id' => 'https://misskey-hub.net/ns#', '@type' => '@id'], 'pixelfed' => (object)['@id' => 'http://pixelfed.org/ns#', '@type' => '@id'], 'lemmy' => (object)['@id' => 'https://join-lemmy.org/ns#', '@type' => '@id'], + 'quote' => (object)['@id' => 'https://w3id.org/fep/044f#', '@type' => '@id'], + 'gts' => (object)['@id' => 'https://gotosocial.org/ns#', '@type' => '@id'], ]; $orig_json = $json; diff --git a/src/Util/Network.php b/src/Util/Network.php index 2172c5a177..06689b7c5d 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -647,7 +647,7 @@ class Network * @param string|null $uri * @return UriInterface|null */ - public static function createUriFromString(string $uri = null): ?UriInterface + public static function createUriFromString(?string $uri): ?UriInterface { if (empty($uri)) { return null; diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index c748c050e6..dfb1e21167 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -22,6 +22,7 @@ use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Network\HTTPClient\Client\HttpClientRequest; use Embera\Embera; use Friendica\Content\Text\BBCode; +use Friendica\Core\Cache\Enum\Duration; use Friendica\Model\Post; /** @@ -459,6 +460,9 @@ class ParseUrl case 'og:description': $siteinfo['text'] = trim($meta_tag['content']); break; + case 'og:updated_time': + $siteinfo['modified'] = DateTimeFormat::utc(trim($meta_tag['content'])); + break; case 'og:site_name': $siteinfo['publisher_name'] = trim($meta_tag['content']); break; @@ -494,16 +498,24 @@ class ParseUrl } } + $siteinfo['schematypes'] = []; + $list = $xpath->query("//script[@type='application/ld+json']"); foreach ($list as $node) { if (!empty($node->nodeValue)) { $jsonld = json_decode($node->nodeValue, true); if (is_array($jsonld)) { - $siteinfo = self::parseParts($siteinfo, $jsonld); + $siteinfo = self::parseParts($siteinfo, $jsonld, true); } } } + $siteinfo['schematypes'] = array_values(array_unique($siteinfo['schematypes'])); + + if (sizeof($siteinfo['schematypes']) === 0) { + unset($siteinfo['schematypes']); + } + $siteinfo = self::getOembedInfo($xpath, $siteinfo); if (!empty($siteinfo['player']['stream'])) { @@ -595,7 +607,7 @@ class ParseUrl foreach (['audio', 'video'] as $element) { if (!empty($siteinfo[$element])) { - array_walk($siteinfo[$element], function (&$media) use ($page_url, &$siteinfo) { + array_walk($siteinfo[$element], function (&$media) use ($page_url) { $url = ''; $embed = ''; $content = ''; @@ -630,9 +642,6 @@ class ParseUrl } if (!empty($embed)) { $media['embed'] = $embed; - if (empty($siteinfo['player']['embed'])) { - $siteinfo['player']['embed'] = $embed; - } } if (!empty($content)) { $media['src'] = $content; @@ -748,16 +757,16 @@ class ParseUrl * * @return array siteinfo */ - private static function parseParts(array $siteinfo, array $jsonld): array + private static function parseParts(array $siteinfo, array $jsonld, bool $root): array { if (!empty($jsonld['@graph']) && is_array($jsonld['@graph'])) { foreach ($jsonld['@graph'] as $part) { if (!empty($part) && is_array($part)) { - $siteinfo = self::parseParts($siteinfo, $part); + $siteinfo = self::parseParts($siteinfo, $part, false); } } } elseif (!empty($jsonld['@type'])) { - $siteinfo = self::parseJsonLd($siteinfo, $jsonld); + $siteinfo = self::parseJsonLd($siteinfo, $jsonld, $root); } elseif (!empty($jsonld)) { $keys = array_keys($jsonld); $numeric_keys = true; @@ -769,7 +778,7 @@ class ParseUrl if ($numeric_keys) { foreach ($jsonld as $part) { if (!empty($part) && is_array($part)) { - $siteinfo = self::parseParts($siteinfo, $part); + $siteinfo = self::parseParts($siteinfo, $part, false); } } } @@ -794,7 +803,7 @@ class ParseUrl * * @return array siteinfo */ - private static function parseJsonLd(array $siteinfo, array $jsonld): array + private static function parseJsonLd(array $siteinfo, array $jsonld, bool $root): array { $type = JsonLD::fetchElement($jsonld, '@type'); if (empty($type)) { @@ -802,6 +811,10 @@ class ParseUrl return $siteinfo; } + if ($root) { + $siteinfo['schematypes'][] = $type; + } + // Silently ignore some types that aren't processed if (in_array($type, ['SiteNavigationElement', 'JobPosting', 'CreativeWork', 'MusicAlbum', 'WPHeader', 'WPSideBar', 'WPFooter', 'LegalService', 'MusicRecording', @@ -1276,7 +1289,7 @@ class ParseUrl $content = JsonLD::fetchElement($jsonld, 'uploadDate'); if (!empty($content) && is_string($content)) { - $media['uploaded'] = trim($content); + $media['uploaded'] = DateTimeFormat::utc($content); } $content = JsonLD::fetchElement($jsonld, 'image'); @@ -1321,6 +1334,22 @@ class ParseUrl DI::logger()->debug('Using Twitter oEmbed', ['url' => $url, 'oembed' => $oembed]); } + if (in_array(parse_url(Strings::normaliseLink($url), PHP_URL_HOST), ['tidal.com'])) { + $oembed = 'https://oembed.tidal.com?url=' . urlencode($url); + DI::logger()->debug('Using Tidal oEmbed', ['url' => $url, 'oembed' => $oembed]); + // @todo Check how to support the parameters listed here: https://developer.tidal.com/documentation/embeds/embeds-code-generator + } + + if (in_array(parse_url(Strings::normaliseLink($url), PHP_URL_HOST), ['link.deezer.com', 'deezer.com', 'www.deezer.com'])) { + $oembed = 'https://api.deezer.com/oembed?url=' . urlencode($url) . '&tracklist=true'; + DI::logger()->debug('Using Deezer oEmbed', ['url' => $url, 'oembed' => $oembed]); + // @see https://developers.deezer.com/api/oembed + } + + if (!$oembed) { + $oembed = self::fetchFromProviderList($url); + } + if (!$oembed) { foreach ($xpath->query("//link[@type='application/json+oembed']") as $link) { /** @var DOMElement $link */ @@ -1346,9 +1375,71 @@ class ParseUrl $data = current($urldata); DI::logger()->debug('Found oEmbed JSON from Embera', ['url' => $url]); } + + if (!isset($data['type']) || !isset($data['provider_url'])) { + return []; + } + + // Some provider return "rich", although they should return "photo" + if ($data['type'] === 'rich' && in_array($data['provider_url'], ['https://www.pixiv.net/', 'https://www.pinterest.com'])) { + $data['type'] = 'photo'; + } + return $data; } + /** + * Fetch the oEmbed provider from the oembed.com provider list + * + * @param string $url The url to fetch the oEmbed provider for + * + * @return string|null The oEmbed url or null if no provider was found + */ + private static function fetchFromProviderList(string $url): ?string + { + $cachekey = 'ParseUrl:fetchFromProviderList'; + + $providers = DI::cache()->get($cachekey); + if (!$providers) { + $providers_content = DI::httpClient()->fetch('https://oembed.com/providers.json', HttpClientAccept::JSON, 0, '', HttpClientRequest::SITEINFO); + if (!$providers_content) { + DI::logger()->warning('Could not fetch oEmbed provider list'); + return null; + } + $providers = json_decode($providers_content, true); + if (!is_array($providers)) { + DI::logger()->warning('Could not decode oEmbed provider list'); + return null; + } + DI::cache()->set($cachekey, $providers, Duration::WEEK); + } + $schemes = []; + foreach ($providers as $provider) { + if (!isset($provider['endpoints']) || !is_array($provider['endpoints'])) { + continue; + } + foreach ($provider['endpoints'] as $endpoint) { + if (!isset($endpoint['schemes']) || !is_array($endpoint['schemes'])) { + $schemes[rtrim($provider['provider_url'], '/') . '/*'] = str_replace('{format}', 'json', $endpoint['url']); + continue; + } + foreach ($endpoint['schemes'] as $scheme) { + $schemes[$scheme] = str_replace('{format}', 'json', $endpoint['url']); + } + } + } + + foreach ($schemes as $scheme => $provider_url) { + $regex = str_replace(['.', '?', '*'], ['\.', '\?', '.*'], $scheme); + if (preg_match('~' . $regex . '~i', $url)) { + $oembed = $provider_url . (strpos($provider_url, '?') === false ? '?' : '&') . 'url=' . urlencode($url); + DI::logger()->debug('Found oEmbed provider from oembed.com list', ['url' => $url, 'oembed' => $oembed]); + return $oembed; + } + } + return null; + } + private static function getSiteinfoFromoEmbed(array $siteinfo, array $data): array { // Youtube provides only basic information to some IP ranges. @@ -1358,31 +1449,34 @@ class ParseUrl $unknown_fields = $data; foreach (['account_type', 'asset_type', 'author_unique_id', 'availability', 'brand', - 'cache_age', 'category', 'currency_code', 'duration', 'embera_using_fake_response', - 'embera_provider_name', 'embed_product_id', 'embed_type', 'flickr_type', - 'height', 'html', 'images','iframe_url', 'is_plus', 'price', 'products', - 'product_expiration', 'product_id', 'quantity', 'referrer', 'safety', 'success', 'type', - 'thumbnail_credit', 'thumbnail_credit_url', 'thumbnail_credit_note', + 'cache_age', 'category', 'collection', 'currency_code', 'duration', 'embera_using_fake_response', + 'embera_provider_name', 'embed_product_id', 'embed_type', 'embed', 'entity', 'flickr_type', + 'height', 'html', 'id', 'images','iframe_url', 'is_plus', 'photographer', 'price', 'products', + 'product_expiration', 'product_id', 'quantity', 'ratio', 'referrer', 'safety', 'success', + 'terms_of_use_url', 'type', 'thumbnail_credit', 'thumbnail_credit_url', 'thumbnail_credit_note', 'thumbnail_height', 'thumbnail_url_with_play_button', 'thumbnail_width', - 'uri', 'url', 'version', 'video_id', 'web_page', 'web_page_short_url', 'width'] as $value) { + 'uri', 'url', 'version', 'video_id', 'web_page', 'web_page_short_url', 'width', 'work_type'] as $value) { unset($unknown_fields[$value]); } $fields = [ - 'title' => 'title', - 'description' => 'text', - 'summary' => 'text', - 'author_name' => 'author_name', - 'author_url' => 'author_url', - 'author' => 'author_name', - 'provider_name' => 'publisher_name', - 'provider_url' => 'publisher_url', - 'thumbnail_url' => 'image', - 'upload_date' => 'published', - 'publication_date' => 'published', - 'license' => 'license_name', - 'license_url' => 'license_url', - 'license_id' => 'license_id', + 'title' => 'title', + 'caption' => 'text', + 'description' => 'text', + 'summary' => 'text', + 'video_description' => 'text', + 'author_name' => 'author_name', + 'author_url' => 'author_url', + 'author' => 'author_name', + 'provider_name' => 'publisher_name', + 'provider_url' => 'publisher_url', + 'image' => 'image', + 'thumbnail_url' => 'image', + 'upload_date' => 'published', + 'publication_date' => 'published', + 'license' => 'license_name', + 'license_url' => 'license_url', + 'license_id' => 'license_id', ]; foreach ($fields as $key => $value) { @@ -1407,12 +1501,16 @@ class ParseUrl private static function getOembedInfo(DOMXPath $xpath, array $siteinfo): array { $data = self::getOembedData($xpath, $siteinfo['url']); - if (empty($data) || !is_array($data)) { + if (!$data) { return $siteinfo; } $siteinfo = self::getSiteinfoFromoEmbed($siteinfo, $data); + if (!self::isWantedEmbed($siteinfo, $data)) { + return $siteinfo; + } + if ($data['type'] == 'video' & empty($siteinfo['player']) && ($data['provider_url'] ?? '') == 'https://www.tiktok.com' && isset($data['embed_product_id']) && isset($data['thumbnail_width']) && isset($data['thumbnail_height'])) { $siteinfo['embed']['type'] = $data['type']; $siteinfo['embed']['html'] = trim($data['html']); @@ -1424,10 +1522,18 @@ class ParseUrl return $siteinfo; } + if ($data['provider_url'] == 'https://www.pinterest.com' && isset($siteinfo['video'])) { + $data['type'] = 'video'; + } + if (!isset($data['html'])) { return $siteinfo; } + if (strpos($data['html'], '<') === 0) { + $data['html'] = html_entity_decode($data['html']); + } + unset($siteinfo['player']); if ($data['type'] == 'rich' && !isset($siteinfo['text'])) { @@ -1455,7 +1561,7 @@ class ParseUrl $curlResult = DI::httpClient()->head($link); $redirect = $curlResult->getRedirectUrl(); if (preg_match('#/(video|broadcasts)/#', $redirect)) { - $siteinfo['embed']['type'] = $data['type']; + $siteinfo['embed']['type'] = 'video'; $siteinfo['embed']['html'] = trim(str_replace('