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 $this->blocklist->exportToFile($filename);
117 * Imports a list of domain patterns and a reason for the block from a CSV
118 * file, e.g. created with the export function.
123 private function importBlockedServers(): int
125 $filename = $this->getArgument(1);
127 $newBlockList = $this->blocklist::extractFromCSVFile($filename);
129 if ($this->blocklist->append($newBlockList)) {
130 $this->out(sprintf("Entries from %s that were not blocked before are now blocked", $filename));
131 Worker::add(Worker::PRIORITY_LOW, 'UpdateBlockedServers');
134 $this->out("Couldn't save the block list");
140 * Prints the whole list of blocked domain patterns including the reason
142 private function printBlockedServers(): void
144 $table = new Console_Table();
145 $table->setHeaders(['Pattern', 'Reason']);
146 foreach ($this->blocklist->get() as $pattern) {
147 $table->addRow($pattern);
150 $this->out($table->getTable());
154 * Adds a domain pattern to the block list
156 * @return int The return code (0 = success, 1 = failed)
158 private function addBlockedServer(): int
160 if (count($this->args) != 3) {
161 throw new CommandArgsException('Add needs a domain pattern and a reason.');
164 $pattern = $this->getArgument(1);
165 $reason = $this->getArgument(2);
167 $result = $this->blocklist->addPattern($pattern, $reason);
170 $this->out(sprintf("The domain pattern '%s' is now updated. (Reason: '%s')", $pattern, $reason));
172 $this->out(sprintf("The domain pattern '%s' is now blocked. (Reason: '%s')", $pattern, $reason));
174 Worker::add(Worker::PRIORITY_LOW, 'UpdateBlockedServers');
177 $this->out(sprintf("Couldn't save '%s' as blocked domain pattern", $pattern));
183 * Removes a domain pattern from the block list
185 * @return int The return code (0 = success, 1 = failed)
187 private function removeBlockedServer(): int
189 if (count($this->args) !== 2) {
190 throw new CommandArgsException('Remove needs a second parameter.');
193 $pattern = $this->getArgument(1);
195 $result = $this->blocklist->removePattern($pattern);
198 $this->out(sprintf("The domain pattern '%s' isn't blocked anymore", $pattern));
199 Worker::add(Worker::PRIORITY_LOW, 'UpdateBlockedServers');
202 $this->out(sprintf("The domain pattern '%s' wasn't blocked.", $pattern));
206 $this->out(sprintf("Couldn't remove '%s' from blocked domain patterns", $pattern));