first commit
This commit is contained in:
commit
47f3f8a6cf
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
.env
|
48
README.md
Normal file
48
README.md
Normal file
@ -0,0 +1,48 @@
|
||||
# shChat Bridge
|
||||
|
||||
A Peer to Peer bridge between Discord and sshChat using [Hyper-Protocol](https://docs.holepunch.to/)
|
||||
|
||||
|
||||
A high-level API for finding and connecting to peers who are interested in a "topic."
|
||||
|
||||
[@hyperswarm/dht](https://docs.holepunch.to/building-blocks/hyperswarm#dht):
|
||||
|
||||
A DHT powering Hyperswarm. Through this DHT, each server is bound to a unique key pair, with the client connecting to the server using the server's public key.
|
||||
|
||||
|
||||
[@hyperswarm/secretstream](https://docs.holepunch.to/building-blocks/hyperswarm#secretstream):
|
||||
|
||||
Secretstream is used to securely create connections between two peers in Hyperswarm.
|
||||
|
||||
## What is HyperSwarm?
|
||||
Hyperswarm allows you to find and connect to peers who are announcing a common "topic". The swarm topic can be anything. This means that, with Hyperswarm, you can discover and connect peers with a shared interest over a distributed network. As an example, we often use Hypercore's discovery key as the swarm topic for discovering peers to replicate with.
|
||||
Once Hyperswarm has discovered peers, nodes in the DHT help those peers connect via a UDP-based hole-punching algorithm that's designed to work well in home networks.
|
||||
|
||||
https://docs.holepunch.to/building-blocks/hyperswarm
|
||||
|
||||
## Usage
|
||||
|
||||
To install:
|
||||
|
||||
`git clone git@git.codingvm.codes:snxraven/sshChatBridge.git`
|
||||
|
||||
`cd sshChatBridge`
|
||||
|
||||
`npm i`
|
||||
|
||||
To run a new topic (room):
|
||||
|
||||
`node bot.js`
|
||||
|
||||
This will log the bot into Discord.
|
||||
|
||||
|
||||
To set a topic use the !set-topic command within the channel you wish to bridge.
|
||||
|
||||
The bot will provide a connection topic hash to connect to.
|
||||
|
||||
Once a peer connects all messages will be sent both ways.
|
||||
|
||||
!leave [TOPIC HASH] will destroy a topic bridge.
|
||||
|
||||
|
165
bot.js
Normal file
165
bot.js
Normal file
@ -0,0 +1,165 @@
|
||||
const Discord = require('discord.js');
|
||||
const Hyperswarm = require('hyperswarm');
|
||||
const crypto = require('hypercore-crypto');
|
||||
const { Client, GatewayIntentBits, Partials, messageLink } = require("discord.js");
|
||||
const goodbye = require('graceful-goodbye')
|
||||
require('dotenv').config()
|
||||
|
||||
const client = new Client({
|
||||
'intents': [
|
||||
GatewayIntentBits.DirectMessages,
|
||||
GatewayIntentBits.MessageContent,
|
||||
GatewayIntentBits.GuildMessages,
|
||||
GatewayIntentBits.Guilds,
|
||||
GatewayIntentBits.GuildBans,
|
||||
GatewayIntentBits.GuildMessages
|
||||
],
|
||||
'partials': [Partials.Channel, Partials.Message, Partials.MessageContent]
|
||||
});
|
||||
|
||||
const topicMap = new Map();
|
||||
goodbye(() => {
|
||||
for(let [channel_id, topic_obj] of topicMap)
|
||||
{
|
||||
topic_obj.swarm.destroy();
|
||||
}
|
||||
})
|
||||
|
||||
client.on('ready', () => {
|
||||
console.log(`Logged in as ${client.user.tag}!`);
|
||||
});
|
||||
|
||||
client.on('messageCreate', msg => {
|
||||
|
||||
if (msg.content.startsWith("!") && !msg.author.bot){
|
||||
const args = msg.content.split(" ");
|
||||
const cmd = args.shift().slice(1);
|
||||
|
||||
if (cmd === "current-topic") {
|
||||
if(topicMap.has(msg.channel.id))
|
||||
{
|
||||
let topic_obj = topicMap.get(msg.channel.id);
|
||||
msg.reply(`The current topic for this channel is: ${topic_obj.topic.toString('hex')}`);
|
||||
}
|
||||
else{
|
||||
msg.reply(`No topic is assigned for this channel`);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd === "join-topic") {
|
||||
if (!args[0]) {
|
||||
msg.reply("Please provide a new topic in hexadecimal format");
|
||||
return;
|
||||
}
|
||||
let topic = crypto.randomBytes(32);
|
||||
let channel_id = args[1];
|
||||
if(!channel_id)
|
||||
{
|
||||
msg.reply("Please provide a channel_id to send this topic's messages")
|
||||
return;
|
||||
}
|
||||
//Check if the given channel_id exists or not.
|
||||
if(!client.channels.cache.get(channel_id))
|
||||
{
|
||||
msg.reply("The provided channel id does not exist.");
|
||||
return;
|
||||
}
|
||||
let swarm;
|
||||
let conns =[];
|
||||
if(topicMap.has(channel_id))
|
||||
{
|
||||
topic_obj = topicMap.get(channel_id);
|
||||
swarm = topic_obj.swarm;
|
||||
conns = topic_obj.conns;
|
||||
}
|
||||
else
|
||||
{
|
||||
swarm = new Hyperswarm();
|
||||
topicMap.set(channel_id, {topic: topic, swarm: swarm, conns: conns});
|
||||
// Join the new topic
|
||||
swarm.join(topic, {
|
||||
lookup: true,
|
||||
announce: true,
|
||||
timeout: 30000
|
||||
});
|
||||
swarm.on('connection', (conn, info) => {
|
||||
console.log(`Connected to a peer for topic ${topic.toString('hex')}`);
|
||||
conns.push(conn);
|
||||
conn.on('data', data => {
|
||||
// Send the message from the topic to the Discord channel
|
||||
client.channels.fetch(channel_id).then(channel=>channel.send(data.toString()))
|
||||
});
|
||||
});
|
||||
client.channels.fetch(channel_id).then(channel => {
|
||||
msg.reply(`Successfully joined topic and sending messages to ${channel}`);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd === "set-topic") {
|
||||
let channel_id = msg.channel.id;
|
||||
//Check if the given channel_id exists or not.
|
||||
if(!client.channels.cache.get(channel_id))
|
||||
{
|
||||
msg.reply("The provided channel id does not exist.");
|
||||
return;
|
||||
}
|
||||
let topic = crypto.randomBytes(32);
|
||||
let swarm;
|
||||
let conns =[];
|
||||
if(topicMap.has(channel_id))
|
||||
{
|
||||
topic_obj = topicMap.get(channel_id);
|
||||
topic_obj.swarm.leave(topic_obj.topic);
|
||||
topic_obj.topic = topic;
|
||||
swarm = topic_obj.swarm;
|
||||
conns = topic_obj.conns;
|
||||
}
|
||||
else{
|
||||
swarm = new Hyperswarm();
|
||||
conns = [];
|
||||
topicMap.set(channel_id, {topic: topic, swarm: swarm, conns: conns});
|
||||
// Join the new topic
|
||||
swarm.join(topic, {
|
||||
lookup: true,
|
||||
announce: true,
|
||||
timeout: 30000
|
||||
});
|
||||
swarm.on('connection', (conn, info) => {
|
||||
console.log(`Connected to a peer for topic ${topic.toString('hex')}`);
|
||||
conns.push(conn);
|
||||
conn.on('data', data => {
|
||||
// Send the message from the topic to the Discord channel
|
||||
client.channels.fetch(channel_id).then(channel=>channel.send(data.toString()))
|
||||
});
|
||||
});
|
||||
}
|
||||
msg.reply(`Successfully set topic ${topic.toString('hex')} for channel ${channel_id}`);
|
||||
}
|
||||
|
||||
if (cmd === "leave-topic") {
|
||||
let channel_id = msg.channel.id;
|
||||
let topic_obj = topicMap.get(channel_id);
|
||||
if (topic_obj) {
|
||||
topic_obj.swarm.leave(topic_obj.topic);
|
||||
topicMap.delete(channel_id);
|
||||
return msg.reply(`Successfully left topic ${topic_obj.topic.toString('hex')} for channel ${channel_id}`);
|
||||
} else {
|
||||
return msg.reply(`No topic is assigned for this channel`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Check if message is sent in a channel with a topic assigned and send it to the topic
|
||||
if(topicMap.has(msg.channel.id) && !msg.author.bot){
|
||||
let topic_obj = topicMap.get(msg.channel.id);
|
||||
let conns = topic_obj.conns;
|
||||
for (const conn of conns) {
|
||||
conn.write(`${msg.author.username}(Discord): ${msg.content}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.login(process.env.TOKEN);
|
22
package.json
Normal file
22
package.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "ssh-chat-bridge",
|
||||
"version": "1.0.0",
|
||||
"description": "A bridge for Discord and sshchat",
|
||||
"main": "bot.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.codingvm.codes:snxraven/sshChatBridge.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"discord.js": "^14.7.1",
|
||||
"dotenv": "^16.0.3",
|
||||
"graceful-goodbye": "^1.2.0",
|
||||
"hypercore-crypto": "^3.3.1",
|
||||
"hyperswarm": "^4.3.5"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user