Forge
csharp1a59f514
1using System.Text.Json;
2using ModelContextProtocol.Protocol;
3
4namespace TelegramRelay.Mcp;
5
6internal static class Handlers
7{
8 public static async Task<string> HandleAsync(string name, IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
9 {
10 if (name == "telegram_get_messages")
11 return await GetMessagesAsync(args, cancellationToken).ConfigureAwait(false);
12 if (name == "telegram_send_message")
13 return await SendMessageAsync(args, cancellationToken).ConfigureAwait(false);
14 if (name == "telegram_create_topic")
15 return await CreateTopicAsync(args, cancellationToken).ConfigureAwait(false);
16 if (name == "telegram_invite_user")
17 return await InviteUserAsync(args, cancellationToken).ConfigureAwait(false);
18 if (name == "telegram_remove_user")
19 return await RemoveUserAsync(args, cancellationToken).ConfigureAwait(false);
20 if (name == "telegram_send_message_to_user")
21 return await SendMessageToUserAsync(args, cancellationToken).ConfigureAwait(false);
22 if (name == "telegram_list_chats")
23 return await ListChatsAsync(cancellationToken).ConfigureAwait(false);
24 if (name == "telegram_edit_message")
25 return await EditMessageAsync(args, cancellationToken).ConfigureAwait(false);
26 if (name == "telegram_delete_message")
27 return await DeleteMessageAsync(args, cancellationToken).ConfigureAwait(false);
28 if (name == "telegram_update_old_messages")
29 return await UpdateOldMessagesAsync(args, cancellationToken).ConfigureAwait(false);
30 throw new ArgumentException($"Unknown tool: {name}");
31 }
32
33 private static async Task<string> GetMessagesAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
34 {
35 if (!args.TryGetValue("chat_id", out var chatIdEl))
36 throw new ArgumentException("chat_id is required");
37 var chatId = chatIdEl.GetInt64();
38 var list = new List<string> { "get-messages", chatId.ToString() };
39 if (args.TryGetValue("topic_id", out var topicIdEl))
40 list.Add(topicIdEl.GetInt32().ToString());
41
42 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
43 if (exitCode != 0)
44 return $"Relay exited with code {exitCode}. Stderr: {stderr}";
45
46 var jsonLine = RelayRunner.ExtractJsonLine(stdout);
47 if (string.IsNullOrEmpty(jsonLine))
48 return "[]";
49 return jsonLine;
50 }
51
52 private static async Task<string> SendMessageAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
53 {
54 if (!args.TryGetValue("chat_id", out var chatIdEl))
55 throw new ArgumentException("chat_id is required");
56 if (!args.TryGetValue("message", out var messageEl))
57 throw new ArgumentException("message is required");
58 var chatId = chatIdEl.GetInt64();
59 var message = messageEl.GetString() ?? "";
60 var list = new List<string> { "send-message-to-chat", chatId.ToString(), message };
61 if (args.TryGetValue("topic_id", out var topicIdEl))
62 list.Add(topicIdEl.GetInt32().ToString());
63
64 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
65 if (exitCode != 0)
66 throw new InvalidOperationException($"Relay exited with code {exitCode}. Stderr: {stderr}");
67 return "OK";
68 }
69
70 private static async Task<string> EditMessageAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
71 {
72 if (!args.TryGetValue("chat_id", out var chatIdEl))
73 throw new ArgumentException("chat_id is required");
74 if (!args.TryGetValue("message_id", out var messageIdEl))
75 throw new ArgumentException("message_id is required");
76 if (!args.TryGetValue("message", out var messageEl))
77 throw new ArgumentException("message is required");
78 var list = new List<string>
79 {
80 "edit-message",
81 chatIdEl.GetInt64().ToString(),
82 messageIdEl.GetInt32().ToString(),
83 messageEl.GetString() ?? ""
84 };
85 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
86 if (exitCode != 0)
87 throw new InvalidOperationException($"Relay exited with code {exitCode}. Stderr: {stderr}");
88 return "OK";
89 }
90
91 private static async Task<string> DeleteMessageAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
92 {
93 if (!args.TryGetValue("chat_id", out var chatIdEl))
94 throw new ArgumentException("chat_id is required");
95 if (!args.TryGetValue("message_id", out var messageIdEl))
96 throw new ArgumentException("message_id is required");
97 var list = new List<string>
98 {
99 "delete-message",
100 chatIdEl.GetInt64().ToString(),
101 messageIdEl.GetInt32().ToString()
102 };
103 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
104 if (exitCode != 0)
105 throw new InvalidOperationException($"Relay exited with code {exitCode}. Stderr: {stderr}");
106 return "OK";
107 }
108
109 private static async Task<string> CreateTopicAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
110 {
111 if (!args.TryGetValue("chat_id", out var chatIdEl))
112 throw new ArgumentException("chat_id is required");
113 if (!args.TryGetValue("title", out var titleEl))
114 throw new ArgumentException("title is required");
115 var list = new List<string> { "create-topic", chatIdEl.GetInt64().ToString(), titleEl.GetString() ?? "" };
116 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
117 if (exitCode != 0)
118 return $"Relay exited with code {exitCode}. Stderr: {stderr}";
119 return stdout.Trim();
120 }
121
122 private static async Task<string> InviteUserAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
123 {
124 if (!args.TryGetValue("chat_id", out var chatIdEl))
125 throw new ArgumentException("chat_id is required");
126 if (!args.TryGetValue("username", out var usernameEl))
127 throw new ArgumentException("username is required");
128 var list = new List<string> { "invite-user", chatIdEl.GetInt64().ToString(), usernameEl.GetString() ?? "" };
129 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
130 if (exitCode != 0)
131 throw new InvalidOperationException($"Relay exited with code {exitCode}. Stderr: {stderr}");
132 return "OK";
133 }
134
135 private static async Task<string> RemoveUserAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
136 {
137 if (!args.TryGetValue("chat_id", out var chatIdEl))
138 throw new ArgumentException("chat_id is required");
139 if (!args.TryGetValue("username", out var usernameEl))
140 throw new ArgumentException("username is required");
141 var list = new List<string> { "delete-user-from-chat", chatIdEl.GetInt64().ToString(), usernameEl.GetString() ?? "" };
142 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
143 if (exitCode != 0)
144 throw new InvalidOperationException($"Relay exited with code {exitCode}. Stderr: {stderr}");
145 return "OK";
146 }
147
148 private static async Task<string> SendMessageToUserAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
149 {
150 if (!args.TryGetValue("username", out var usernameEl))
151 throw new ArgumentException("username is required");
152 if (!args.TryGetValue("message", out var messageEl))
153 throw new ArgumentException("message is required");
154 var list = new List<string> { "send-message-to-user", usernameEl.GetString() ?? "", messageEl.GetString() ?? "" };
155 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
156 if (exitCode != 0)
157 throw new InvalidOperationException($"Relay exited with code {exitCode}. Stderr: {stderr}");
158 return "OK";
159 }
160
161 private static async Task<string> ListChatsAsync(CancellationToken cancellationToken)
162 {
163 var list = new List<string> { "list-chats" };
164 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
165 if (exitCode != 0)
166 return $"Relay exited with code {exitCode}. Stderr: {stderr}";
167 var line = RelayRunner.ExtractJsonLine(stdout);
168 return string.IsNullOrEmpty(line) ? "[]" : line;
169 }
170
171 private static async Task<string> UpdateOldMessagesAsync(IReadOnlyDictionary<string, JsonElement> args, CancellationToken cancellationToken)
172 {
173 if (!args.TryGetValue("chat_id", out var chatIdEl))
174 throw new ArgumentException("chat_id is required");
175 var list = new List<string> { "update-old-messages", chatIdEl.GetInt64().ToString() };
176 if (args.TryGetValue("topic_id", out var topicIdEl))
177 list.Add(topicIdEl.GetInt32().ToString());
178 var (stdout, stderr, exitCode) = await RelayRunner.RunAsync(list, cancellationToken).ConfigureAwait(false);
179 if (exitCode != 0)
180 return $"Relay exited with code {exitCode}. Stderr: {stderr}";
181 return stdout.Trim();
182 }
183}
184
View only · write via MCP/CIDE