3 * @copyright Copyright (C) 2010-2023, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Console;
24 use Asika\SimpleConsole\CommandArgsException;
25 use Asika\SimpleConsole\Console;
27 use Friendica\Core\Worker;
28 use Friendica\Moderation\DomainPatternBlocklist;
31 * Manage blocked servers
33 * With this tool, you can list the current blocked servers
34 * or you can add / remove a blocked server from the list
36 class ServerBlock extends Console
38 protected $helpOptions = ['h', 'help', '?'];
40 /** @var DomainPatternBlocklist */
43 protected function getHelp(): string
46 console serverblock - Manage blocked server domain patterns
48 bin/console serverblock [-h|--help|-?] [-v]
49 bin/console serverblock add <pattern> <reason> [-h|--help|-?] [-v]
50 bin/console serverblock remove <pattern> [-h|--help|-?] [-v]
51 bin/console serverblock export <filename>
52 bin/console serverblock import <filename>
55 With this tool, you can list the current blocked server domain patterns
56 or you can add / remove a blocked server domain pattern from the list.
57 Using the export and import options you can share your server blocklist
58 with other node admins by CSV files.
60 Patterns are case-insensitive shell wildcard comprising the following special characters:
61 - * : Any number of characters
62 - ? : Any single character
63 - [<char1><char2>...] : char1 or char2 or...
66 -h|--help|-? Show help information
67 -v Show more debug information.
71 public function __construct(DomainPatternBlocklist $blocklist, $argv = null)
73 parent::__construct($argv);
75 $this->blocklist = $blocklist;
78 protected function doExecute(): int
80 if (count($this->args) == 0) {
81 $this->printBlockedServers();
85 switch ($this->getArgument(0)) {
87 return $this->addBlockedServer();
89 return $this->removeBlockedServer();
91 return $this->exportBlockedServers();
93 return $this->importBlockedServers();
95 throw new CommandArgsException('Unknown command.');
100 * Exports the list of blocked domain patterns including the reason for the
101 * block to a CSV file.
106 private function exportBlockedServers(): int
108 $filename = $this->getArgument(1);
110 if (empty($filename)) {
111 $this->out('A file name is required, e.g. ./bin/console serverblock export backup.csv');
115 $this->blocklist->exportToFile($filename);
122 * Imports a list of domain patterns and a reason for the block from a CSV
123 * file, e.g. created with the export function.
128 private function importBlockedServers(): int
130 $filename = $this->getArgument(1);
132 $newBlockList = $this->blocklist::extractFromCSVFile($filename);
134 if ($this->blocklist->append($newBlockList)) {
135 $this->out(sprintf("Entries from %s that were not blocked before are now blocked", $filename));
136 Worker::add(Worker::PRIORITY_LOW, 'UpdateBlockedServers');
139 $this->out("Couldn't save the block list");
145 * Prints the whole list of blocked domain patterns including the reason
147 private function printBlockedServers(): void
149 $table = new Console_Table();
150 $table->setHeaders(['Pattern', 'Reason']);
151 foreach ($this->blocklist->get() as $pattern) {
152 $table->addRow($pattern);
155 $this->out($table->getTable());
159 * Adds a domain pattern to the block list
161 * @return int The return code (0 = success, 1 = failed)
163 private function addBlockedServer(): int
165 if (count($this->args) != 3) {
166 throw new CommandArgsException('Add needs a domain pattern and a reason.');
169 $pattern = $this->getArgument(1);
170 $reason = $this->getArgument(2);
172 $result = $this->blocklist->addPattern($pattern, $reason);
175 $this->out(sprintf("The domain pattern '%s' is now updated. (Reason: '%s')", $pattern, $reason));
177 $this->out(sprintf("The domain pattern '%s' is now blocked. (Reason: '%s')", $pattern, $reason));
179 Worker::add(Worker::PRIORITY_LOW, 'UpdateBlockedServers');
182 $this->out(sprintf("Couldn't save '%s' as blocked domain pattern", $pattern));
188 * Removes a domain pattern from the block list
190 * @return int The return code (0 = success, 1 = failed)
192 private function removeBlockedServer(): int
194 if (count($this->args) !== 2) {
195 throw new CommandArgsException('Remove needs a second parameter.');
198 $pattern = $this->getArgument(1);
200 $result = $this->blocklist->removePattern($pattern);
203 $this->out(sprintf("The domain pattern '%s' isn't blocked anymore", $pattern));
204 Worker::add(Worker::PRIORITY_LOW, 'UpdateBlockedServers');
207 $this->out(sprintf("The domain pattern '%s' wasn't blocked.", $pattern));
211 $this->out(sprintf("Couldn't remove '%s' from blocked domain patterns", $pattern));