Skip to content

Commit

Permalink
revert: ws change
Browse files Browse the repository at this point in the history
  • Loading branch information
Prioq committed Oct 23, 2024
1 parent a2c987d commit 3fa97ed
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 115 deletions.
117 changes: 34 additions & 83 deletions lib/client/onNotification.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
const WebSocket = require('ws');
// Dependencies
const signalR = require('@microsoft/signalr');
const events = require('events');
const { HttpsProxyAgent } = require('https-proxy-agent'); // For proxying the WebSocket connection

// Includes
const getSession = require('../util/getSession.js').func;
const settings = require('../../settings.json');

// Args
exports.optional = ['proxyUrl','jar']; // Add proxyUrl as an optional argument
exports.optional = ['jar'];

// Docs
/**
Expand All @@ -17,7 +17,7 @@ exports.optional = ['proxyUrl','jar']; // Add proxyUrl as an optional argument
* @returns An EventEmitter that emits when you get a notification.
* @example const noblox = require("noblox.js")
* // Login using your cookie
* const notification = noblox.onNotification({ proxyUrl: 'http://your-proxy-server.com:8080' })
* const notification = noblox.onNotification()
* notification.on("data", function(data) {
* console.log("New notification! ", data)
* })
Expand All @@ -29,10 +29,8 @@ exports.optional = ['proxyUrl','jar']; // Add proxyUrl as an optional argument

// Define
exports.func = function (args) {
const maxRetries = settings.event.maxRetries || 5;
let retryCount = 0;
const max = settings.event.maxRetries;
const notifications = new events.EventEmitter();
let ws;

async function connect() {
try {
Expand All @@ -41,89 +39,42 @@ exports.func = function (args) {
}
const session = getSession({ jar: args.jar });

const url = 'wss://realtime-signalr.roblox.com/userhub'; // WebSocket endpoint
let options = {
headers: {
Cookie: `.ROBLOSECURITY=${session};`
// Create a SignalR HubConnectionBuilder instance
const userNotificationConnection = new signalR.HubConnectionBuilder()
.withUrl('https://realtime-signalr.roblox.com/userhub', {
transport: signalR.HttpTransportType.WebSockets,
skipNegotiation: true,
headers: {
Cookie: '.ROBLOSECURITY=' + session + ';'
}
})
.withAutomaticReconnect()
.build();

notifications.on('close', async (internal) => {
if (internal) {
return;
}
};
await userNotificationConnection.stop();
notifications.emit('closed');
});

// If a proxy URL is provided, use it
if (args.proxyUrl) {
const proxyAgent = new HttpsProxyAgent(args.proxyUrl);
options.agent = proxyAgent;
}
// Handle incoming notifications
userNotificationConnection.on('notification', (name, message) => {
notifications.emit('data', name, JSON.parse(message));
});

try {
ws = new WebSocket(url, [], options);

} catch (err) {
notifications.emit('error', new Error('Failed to create WebSocket: ' + err.message));
// Start the connection
if (!userNotificationConnection) {
return;
}

ws.on('open', () => {
retryCount = 0;
try {
await userNotificationConnection.start();
notifications.emit('connect');

// Send the protocol initialization message on connect, including the special character
const initMessage = `{"protocol":"json","version":1}\u001e`; // Adding \u001e (0x1E) to indicate the end of the message
ws.send(initMessage);
});

ws.on('message', (data) => {
// Strip off control characters like \x1e before attempting to parse
const cleanedData = data.toString().replace(/\u001e/g, ''); // Removes the 0x1E character

try {
const parsedData = JSON.parse(cleanedData);

// Check if it's the expected type and target
if (parsedData.type === 1 && parsedData.target === 'notification') {
const [name, message] = parsedData.arguments;


// parse the message

const parsedMessage = JSON.parse(message);

// Format the data into the desired structure


// Emit the formatted data
notifications.emit('data', name, parsedMessage);

} else {
// Handle other types of messages if needed
notifications.emit('data', parsedData);
}
} catch (err) {
notifications.emit('error', new Error('Failed to parse notification: ' + err.message));
}
});


ws.on('close', () => {
if (retryCount < maxRetries) {
retryCount++;
setTimeout(connect, 1000 * retryCount); // Exponential backoff for retries
} else {
notifications.emit('error', new Error('Max retries reached. Connection closed.'));
notifications.emit('closed');
}
});

ws.on('error', (err) => {
notifications.emit('error', new Error('WebSocket error: ' + err.message));
ws.close(); // Ensure connection is closed if there's an error
});

notifications.on('close', () => {
if (ws) {
ws.close();
notifications.emit('closed');
}
});
} catch (err) {
notifications.emit('error', new Error('Failed to start connection: ' + err.message));
}
} catch (err) {
notifications.emit('error', err);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/friends/onFriendRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const events = require('events')
const onNotification = require('../client/onNotification.js').func

// Args
exports.optional = ['proxyUrl','jar']
exports.optional = ['jar']

// Docs
/**
Expand Down Expand Up @@ -34,7 +34,7 @@ exports.func = function (args) {
jar = jar()
}
const onFriendRequest = new events.EventEmitter()
const notifications = onNotification({ jar, proxyUrl: args.proxyUrl })
const notifications = onNotification({ jar })

notifications.on('data', function (name, message) {
if (name === 'FriendshipNotifications' && message.Type === 'FriendshipRequested') {
Expand Down
4 changes: 2 additions & 2 deletions lib/friends/onFriendshipCreated.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const events = require('events')
const onNotification = require('../client/onNotification.js').func

// Args
exports.optional = ['proxyUrl','jar']
exports.optional = ['jar']

// Docs
/**
Expand Down Expand Up @@ -34,7 +34,7 @@ exports.func = function (args) {
jar = jar()
}
const onFriendshipCreated = new events.EventEmitter()
const notifications = onNotification({ jar, proxyUrl: args.proxyUrl })
const notifications = onNotification({ jar })
notifications.on('data', function (name, message) {
if (name === 'FriendshipNotifications' && message.Type === 'FriendshipCreated') {
onFriendshipCreated.emit('data', message.EventArgs)
Expand Down
48 changes: 26 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
"cheerio": "^1.0.0-rc.10",
"entities": "^5.0.0",
"figlet": "^1.7.0",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.5",
"postman-request": "^2.88.1-postman.34"
},
"license": "MIT",
Expand All @@ -41,13 +39,13 @@
"homepage": "https://github.com/noblox/noblox.js",
"devDependencies": {
"@auto-it/conventional-commits": "^11.2.0",
"JSONStream": "^1.3.1",
"auto": "^11.2.0",
"better-docs": "2.7.3",
"dotenv": "16.4.5",
"jest": "^29.7.0",
"jest-extended": "^4.0.2",
"jsdoc": "4.0.3",
"JSONStream": "^1.3.1",
"standard": "^17.1.0"
},
"jest": {
Expand Down Expand Up @@ -79,4 +77,4 @@
"node": ">=18.18"
},
"packageManager": "[email protected]+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
}
}
4 changes: 2 additions & 2 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2541,12 +2541,12 @@ declare module "noblox.js" {
/**
* 🔐 Fires when new friend requests are received.
*/
function onFriendRequest(proxyUrl?: string, jar?: CookieJar): OnFriendRequestEventEmitter;
function onFriendRequest(jar?: CookieJar): OnFriendRequestEventEmitter;

/**
* 🔐 Fires when a new friendship is created.
*/
function onFriendshipCreated(proxyUrl?: string, jar?: CookieJar): OnFriendShipCreationEventEmitter;
function onFriendshipCreated(jar?: CookieJar): OnFriendShipCreationEventEmitter;

/**
* 🔐 Fires whenever a new message is received. Because it relies on `onNotification`, the logged in user's notification stream for messages must be enabled; however, it is one of the true events and does not rely on short polling.
Expand Down

0 comments on commit 3fa97ed

Please sign in to comment.