]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/commands/DaemonCommand.java
Refactor command creation
[signal-cli] / src / main / java / org / asamk / signal / commands / DaemonCommand.java
1 package org.asamk.signal.commands;
2
3 import net.sourceforge.argparse4j.impl.Arguments;
4 import net.sourceforge.argparse4j.inf.Namespace;
5 import net.sourceforge.argparse4j.inf.Subparser;
6
7 import org.asamk.signal.DbusConfig;
8 import org.asamk.signal.DbusReceiveMessageHandler;
9 import org.asamk.signal.JsonDbusReceiveMessageHandler;
10 import org.asamk.signal.JsonWriter;
11 import org.asamk.signal.OutputType;
12 import org.asamk.signal.OutputWriter;
13 import org.asamk.signal.PlainTextWriter;
14 import org.asamk.signal.commands.exceptions.CommandException;
15 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
16 import org.asamk.signal.dbus.DbusSignalControlImpl;
17 import org.asamk.signal.dbus.DbusSignalImpl;
18 import org.asamk.signal.manager.Manager;
19 import org.freedesktop.dbus.connections.impl.DBusConnection;
20 import org.freedesktop.dbus.exceptions.DBusException;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.io.IOException;
25 import java.util.List;
26 import java.util.concurrent.TimeUnit;
27
28 public class DaemonCommand implements MultiLocalCommand {
29
30 private final static Logger logger = LoggerFactory.getLogger(DaemonCommand.class);
31
32 @Override
33 public String getName() {
34 return "daemon";
35 }
36
37 @Override
38 public void attachToSubparser(final Subparser subparser) {
39 subparser.help("Run in daemon mode and provide an experimental dbus interface.");
40 subparser.addArgument("--system")
41 .action(Arguments.storeTrue())
42 .help("Use DBus system bus instead of user bus.");
43 subparser.addArgument("--ignore-attachments")
44 .help("Don’t download attachments of received messages.")
45 .action(Arguments.storeTrue());
46 }
47
48 @Override
49 public List<OutputType> getSupportedOutputTypes() {
50 return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
51 }
52
53 @Override
54 public void handleCommand(
55 final Namespace ns, final Manager m, final OutputWriter outputWriter
56 ) throws CommandException {
57 boolean ignoreAttachments = ns.getBoolean("ignore-attachments");
58
59 DBusConnection.DBusBusType busType;
60 if (ns.getBoolean("system")) {
61 busType = DBusConnection.DBusBusType.SYSTEM;
62 } else {
63 busType = DBusConnection.DBusBusType.SESSION;
64 }
65
66 try (var conn = DBusConnection.getConnection(busType)) {
67 var objectPath = DbusConfig.getObjectPath();
68 var t = run(conn, objectPath, m, outputWriter, ignoreAttachments);
69
70 conn.requestBusName(DbusConfig.getBusname());
71
72 try {
73 t.join();
74 } catch (InterruptedException ignored) {
75 }
76 } catch (DBusException | IOException e) {
77 logger.error("Dbus command failed", e);
78 throw new UnexpectedErrorException("Dbus command failed");
79 }
80 }
81
82 @Override
83 public void handleCommand(
84 final Namespace ns, final List<Manager> managers, final SignalCreator c, final OutputWriter outputWriter
85 ) throws CommandException {
86 boolean ignoreAttachments = ns.getBoolean("ignore-attachments");
87
88 DBusConnection.DBusBusType busType;
89 if (ns.getBoolean("system")) {
90 busType = DBusConnection.DBusBusType.SYSTEM;
91 } else {
92 busType = DBusConnection.DBusBusType.SESSION;
93 }
94
95 try (var conn = DBusConnection.getConnection(busType)) {
96 final var signalControl = new DbusSignalControlImpl(c, m -> {
97 try {
98 final var objectPath = DbusConfig.getObjectPath(m.getUsername());
99 return run(conn, objectPath, m, outputWriter, ignoreAttachments);
100 } catch (DBusException e) {
101 logger.error("Failed to export object", e);
102 return null;
103 }
104 }, DbusConfig.getObjectPath());
105 conn.exportObject(signalControl);
106
107 for (var m : managers) {
108 signalControl.addManager(m);
109 }
110
111 conn.requestBusName(DbusConfig.getBusname());
112
113 signalControl.run();
114 } catch (DBusException | IOException e) {
115 logger.error("Dbus command failed", e);
116 throw new UnexpectedErrorException("Dbus command failed");
117 }
118 }
119
120 private Thread run(
121 DBusConnection conn, String objectPath, Manager m, OutputWriter outputWriter, boolean ignoreAttachments
122 ) throws DBusException {
123 conn.exportObject(new DbusSignalImpl(m, objectPath));
124
125 logger.info("Exported dbus object: " + objectPath);
126
127 final var thread = new Thread(() -> {
128 while (!Thread.interrupted()) {
129 try {
130 final var receiveMessageHandler = outputWriter instanceof JsonWriter
131 ? new JsonDbusReceiveMessageHandler(m, (JsonWriter) outputWriter, conn, objectPath)
132 : new DbusReceiveMessageHandler(m, (PlainTextWriter) outputWriter, conn, objectPath);
133 m.receiveMessages(1, TimeUnit.HOURS, false, ignoreAttachments, receiveMessageHandler);
134 break;
135 } catch (IOException e) {
136 logger.warn("Receiving messages failed, retrying", e);
137 } catch (InterruptedException ignored) {
138 break;
139 }
140 }
141 });
142
143 thread.start();
144
145 return thread;
146 }
147 }