Add message sending, adding docs

This commit is contained in:
KillerBossOriginal 2023-08-04 19:19:21 +02:00
parent 4f2da16910
commit efbba335a7
7 changed files with 119 additions and 51 deletions

View file

@ -17,3 +17,10 @@ main() {
- id: String
- token: String
url overrides id and token
## Credits
We took inspiration from [discord.js](https://github.com/discordjs/discord.js) and [Grapes-discord.grapes](https://github.com/BlackdestinyXX/Grapes-discord.grapes).
### Packages
- [http](https://pub.dev/packages/http) by dart.dev (BSD-3-Clause)
- [events-emitter](https://pub.dev/packages/events_emitter) by drafakiller.com (MIT)

View file

@ -1,10 +0,0 @@
import 'package:http/http.dart';
void handleCode(Response res) async {
int code = res.statusCode;
switch (code) {
default:
break;
}
return;
}

View file

View file

@ -1,15 +1,17 @@
import "dart:async";
import "dart:io";
import "package:tn_discord/src/types.dart";
import "requests.dart";
import "dart:convert";
import "package:events_emitter/events_emitter.dart";
import "types.dart";
import "requests.dart";
final version = "10";
final apiURL = "https://discord.com/api/v$version";
/// This function calculate the intent number required from the gateway.
/// [intents] is a list of multiples of two. You can use GatewayIntentBits class.
/// Return a number.
int calculateIntents(List<int> intents) {
int intentsNumber = 0;
@ -20,6 +22,8 @@ int calculateIntents(List<int> intents) {
return intentsNumber;
}
/// The main hub for interacting with the Discord API, and the starting point for any bot.
class Client extends EventEmitter {
String? token;
int intents;
@ -29,8 +33,13 @@ class Client extends EventEmitter {
dynamic guilds;
dynamic ready;
/// Create a new Client.
/// [intents] Intents to enable for this connection, it's a multiple of two.
Client({this.intents = 0});
/// Logs the client in, establishing a WebSocket connection to Discord.
/// [token] is the token of the account to log in with.
/// Get the token from https://discord.dev
login(String token) async {
final websocket = await requestWebSocketURL();
@ -44,7 +53,7 @@ class Client extends EventEmitter {
"token": token,
"intents": intents,
"properties": {
"os": "linux",
"os": Platform.operatingSystem,
"browser": "tn_discord",
"device": "tn_discord",
},
@ -81,10 +90,10 @@ class Client extends EventEmitter {
List<Guild> gg = [];
for (dynamic g in i) {
gg.add(Guild(g));
gg.add(Guild(sender, g));
}
guilds = GuildManager(gg);
guilds = GuildManager(sender, gg);
int n = i.length;
@ -112,7 +121,7 @@ class Client extends EventEmitter {
sessionID = event["d"]["session_id"];
break;
case "GUILD_CREATE":
guilds.cache.set(event["d"]["id"], Guild(event["d"]));
guilds.cache.set(event["d"]["id"], Guild(sender, event["d"]));
if (n > 1) {
n--;
} else {

View file

@ -1,4 +1,5 @@
import 'main.dart';
import 'types.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
@ -34,13 +35,13 @@ Future<String> requestWebSocketURL() async {
}
class Sender {
String? token;
final String? _token;
Map<String, String> headers = {};
Sender(token) {
Sender(this._token) {
headers = {
"Content-Type": "application/json",
"Authorization": "Bot $token"
"Authorization": "Bot $_token",
};
}
@ -50,4 +51,29 @@ class Sender {
res = json.decode(res.body);
return res;
}
Future send(Message msg, String cid) async {
final url = Uri.parse("$apiURL/channels/$cid/messages");
dynamic res = await http.post(url, headers: headers, body: json.encode(msg.exportable()));
res = json.decode(res.body);
return res;
}
Future fetchGuild(String id) async {
dynamic res = await http.get(Uri.parse("$apiURL/guilds/$id"), headers: headers);
if (res.statusCode != 200) {
throw Exception("Error ${res.statusCode} receiving the guild");
}
res = json.decode(res.body);
return res;
}
Future fetchChannel(String id) async {
dynamic res = await http.get(Uri.parse("$apiURL/channels/$id"), headers: headers);
if (res.statusCode != 200) {
throw Exception("Error ${res.statusCode} receiving the channel");
}
res = json.decode(res.body);
return res;
}
}

View file

@ -2,7 +2,9 @@
import "dart:convert";
import "package:http/http.dart" as http;
import "main.dart";
import "requests.dart";
/// A list of all Gateway Intents Bits.
class GatewayIntentBits {
static const Guilds = 1;
static const GuildMembers = 2;
@ -25,15 +27,20 @@ class GatewayIntentBits {
static const AutoModerationExecution = 2097152;
}
/// A collection of variables. Like NodeJS' Map and discordjs' Collections
/// This will be moved to a separate package in the future.
class Collection {
final Map<String, dynamic> _variables = {};
/// Create a new Collection
Collection();
/// Adds a new element with key [key] and value [value] to the Map. If an element with the same key already exists, the element will be updated.
dynamic set(String key, dynamic value) {
_variables[key] = value;
return value;
}
/// Returns [key] from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
dynamic get(String key) {
if (_variables[key] == null) {
throw Exception("Variable not found for $key");
@ -41,43 +48,56 @@ class Collection {
return _variables[key];
}
/// Removes [key] from the Map object.
void remove(String key) {
_variables.remove(key);
}
/// Alias of [remove]
void delete(String key) {
remove(key);
}
/// Sum to the value of [key] to [value].
dynamic add(String key, num value) {
_variables[key] += value;
return value + _variables[key];
}
/// Subtract [value] from the value of [key].
dynamic subtract(String key, num value) {
_variables[key] -= value;
return value - _variables[key];
return _variables[key] - value;
}
/// Returns all the variables as a Map.
Map<String, dynamic> getAll() {
return _variables;
}
/// Returns all the variables' keys as a List.
List<String> keys() {
return _variables.keys.toList();
}
/// Returns all the variables' values as a List.
List<dynamic> values() {
return _variables.values.toList();
}
}
/// Represents a guild (aka server) on Discord.
class Guild {
String id = '';
String name = '';
String? owner;
String? description;
ChannelManager channels = ChannelManager([]);
MemberManager members = MemberManager([], '');
RoleManager roles = RoleManager([]);
late ChannelManager channels;
late MemberManager members;
late RoleManager roles;
final Sender _sender;
Guild(Map data) {
Guild(this._sender, Map data) {
id = data["id"];
name = data["name"];
description = data["description"];
@ -86,9 +106,9 @@ class Guild {
if(data["channels"] != null && data["members"] != null && data["roles"] != null) {
List<Channel> cc = [];
for (var c in data["channels"]) {
cc.add(Channel(c));
cc.add(Channel(_sender, c));
}
channels = ChannelManager(cc);
channels = ChannelManager(_sender, cc);
List<Member> mm = [];
for (var m in data["members"]) {
@ -101,25 +121,27 @@ class Guild {
rr.add(Role(r));
}
roles = RoleManager(rr);
} else {
channels = ChannelManager(_sender, []);
members = MemberManager([], id);
roles = RoleManager([]);
}
}
}
class GuildManager {
final Collection cache = Collection();
final Sender _sender;
GuildManager(List<Guild> guilds) {
GuildManager(this._sender, List<Guild> guilds) {
for (var guild in guilds) {
cache.set(guild.id, guild);
}
}
Future<Guild> fetch(String id) async {
var res = await http.get(Uri.parse("$apiURL/guilds/$id"));
if (res.statusCode != 200) {
throw Exception("Error ${res.statusCode} receiving the guild");
}
final guild = Guild(json.decode(res.body));
var res = await _sender.fetchGuild(id);
final guild = Guild(_sender, res);
cache.set(guild.id, guild);
return guild;
}
@ -128,28 +150,32 @@ class GuildManager {
class Channel {
String id = '';
String name = '';
final Sender _sender;
Channel(Map data) {
Channel(this._sender, data) {
id = data["id"];
name = data["name"];
}
Future<MessageSent> send(Message message) async {
await _sender.send(message, id);
return MessageSent(message, id: id);
}
}
class ChannelManager {
final Collection cache = Collection();
final Sender _sender;
ChannelManager(List<Channel> channels) {
ChannelManager(this._sender, List<Channel> channels) {
for (var channel in channels) {
cache.set(channel.id, channel);
}
}
Future<Channel> fetch(String id) async {
var res = await http.get(Uri.parse("$apiURL/channels/$id"));
if (res.statusCode != 200) {
throw Exception("Error ${res.statusCode} receiving the channel");
}
dynamic channel = Channel(json.decode(res.body));
var res = await _sender.fetchChannel(id);
dynamic channel = Channel(_sender, res);
cache.set(channel.id, channel);
return channel;
}
@ -157,12 +183,10 @@ class ChannelManager {
class Member {
String id = '';
String name = '';
User user = User({});
Member(Map data) {
id = data["user"]["id"];
name = data["user"]["username"];
user = User(data["user"]);
}
}
@ -253,4 +277,23 @@ class UserManager {
}
typedef Embed = Map<String, String>;
typedef Message = Map<String, String>;
/// Represents a message on Discord.
class Message {
String? content;
Message({ this.content });
exportable() {
return {
"content": content,
};
}
}
/// Represents a sent message on Discord.
class MessageSent extends Message {
String id = '';
MessageSent(Message msg, { required this.id }) {
content = msg.content;
}
}

View file

@ -1,7 +1,6 @@
import "dart:convert";
import "package:http/http.dart";
import "error_handler.dart";
import 'requests.dart';
import "types.dart";
import "util.dart";
@ -25,7 +24,6 @@ class WebhookClient {
Map<String, String> body = {"content": content};
Response res = await sendWH(body, token, id);
handleCode(res);
return json.decode(res.body);
}
@ -35,7 +33,6 @@ class WebhookClient {
Response res = await sendWH(body, token, id);
handleCode(res);
return json.decode(res.body);
}
@ -43,7 +40,6 @@ class WebhookClient {
Map<String, String> body = {"content": content};
Response res = await editWH(body, token, this.id, id);
handleCode(res);
return json.decode(res.body);
}
@ -51,20 +47,17 @@ class WebhookClient {
Map body = {"content": content, "embeds": embeds};
Response res = await editWH(body, token, this.id, id);
handleCode(res);
return json.decode(res.body);
}
Future<Map<String, dynamic>> get(String id) async {
Response res = await getWH(token, this.id, id);
handleCode(res);
return json.decode(res.body);
}
Future<Map<String, dynamic>> delete(String id) async {
Response res = await deleteWH(token, this.id, id);
handleCode(res);
return json.decode(res.body);
}