/// bobcord_dart.dart — SDK BobCord (REST + builders) /// User + Bot + EmbedBuilder + ActionRow / Button / WebAction /// API: https://aml-s9xx-box.taildd440a.ts.net/api/v1.1 /// deps: http import 'dart:convert'; import 'package:http/http.dart' as http; const defaultBase = 'https://aml-s9xx-box.taildd440a.ts.net/api/v1.1'; Map webActionConfirm(String title, String body, [Map? then]) { final o = {'type': 'confirm', 'title': title, 'body': body}; if (then != null) o['then'] = then; return o; } Map webActionSendMessage(String content, {String? channel, int? serverId, Map? confirm}) { final o = {'type': 'send_message', 'content': content}; if (channel != null) o['channel'] = channel; if (serverId != null) o['server_id'] = serverId; if (confirm != null) o['confirm'] = confirm; return o; } Map webActionReact(String emoji, {dynamic messageId = 'self', Map? confirm}) { final o = {'type': 'react', 'emoji': emoji, 'message_id': messageId}; if (confirm != null) o['confirm'] = confirm; return o; } Map button(String label, {String style = 'SECONDARY', String? customId, String? url, Map? webAction, bool disabled = false}) { style = style.toUpperCase(); final o = {'type': 'BUTTON', 'style': style, 'label': label, 'disabled': disabled}; if (style == 'LINK') { if (url == null) throw ArgumentError('LINK requires url'); o['url'] = url; } else { if (customId == null) throw ArgumentError('BUTTON requires custom_id'); o['custom_id'] = customId; } if (style == 'WEB_ACTION') { if (webAction == null) throw ArgumentError('WEB_ACTION requires web_action'); o['web_action'] = webAction; } return o; } Map actionRow(List> components) => { 'type': 'ACTION_ROW', 'components': components.take(5).toList(), }; List> actionRows(List> rows) => rows.take(4).toList(); class EmbedBuilder { final Map _data = {'fields': >[]}; EmbedBuilder title(String t) { _data['title'] = t; return this; } EmbedBuilder description(String d) { _data['description'] = d; return this; } EmbedBuilder color(int c) { _data['color'] = c & 0xFFFFFF; return this; } EmbedBuilder addField(String name, String value, {bool inline = false}) { (_data['fields'] as List).add({'name': name, 'value': value, 'inline': inline}); return this; } EmbedBuilder footer(String text) { _data['footer'] = {'text': text}; return this; } Map build() => Map.from(_data); } class User { final String token; String baseUrl; Map? me; User(this.token, {this.baseUrl = defaultBase}); Future request(String method, String path, [Map? body]) async { final uri = Uri.parse('${baseUrl.replaceAll(RegExp(r'/$'), '')}/${path.replaceFirst(RegExp(r'^/'), '')}'); final headers = {'Authorization': 'Bearer $token', 'Content-Type': 'application/json'}; late http.Response res; final encoded = body == null ? null : jsonEncode(body); switch (method) { case 'GET': res = await http.get(uri, headers: headers); break; case 'POST': res = await http.post(uri, headers: headers, body: encoded); break; case 'PUT': res = await http.put(uri, headers: headers, body: encoded); break; case 'DELETE': res = await http.delete(uri, headers: headers, body: encoded); break; default: res = await http.get(uri, headers: headers); } if (res.statusCode == 204) return null; final data = res.body.isEmpty ? {} : jsonDecode(res.body); if (res.statusCode >= 400) throw Exception('HTTP ${res.statusCode}: $data'); return data; } Future> login() async { final data = await request('GET', '/me') as Map; me = (data['user'] as Map?) ?? data; return me!; } Future send(String content, {String channel = 'général', int serverId = 1, List? embeds, List? actionRows, dynamic attachments}) { final body = {'content': content, 'channel': channel, 'server_id': serverId}; if (embeds != null) body['embeds'] = embeds; if (attachments != null) body['attachments'] = attachments; if (actionRows != null) body['action_rows'] = actionRows; return request('POST', '/message', body); } } class Bot extends User { Bot(super.token, {super.baseUrl}); }