├── image-1.png ├── image-2.png ├── .gitignore ├── package.json ├── utils ├── banner.js ├── logger.js ├── scripts.js └── gateway.js ├── LICENSE ├── README.md └── main.js /image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zlkcyber/streamAi/HEAD/image-1.png -------------------------------------------------------------------------------- /image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zlkcyber/streamAi/HEAD/image-2.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | tes 4 | vana 5 | userIds.txt 6 | proxies.txt -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "name": "stream-ai", 4 | "version": "1.0.0", 5 | "description": "Mine Data, Fuel AI, Earn Rewards Join the Stream AI Revolution", 6 | "main": "main.js", 7 | "scripts": { 8 | "start": "node main.js" 9 | }, 10 | "author": "@zlkcyber", 11 | "license": "MIT", 12 | "dependencies": { 13 | "fs": "^0.0.1-security", 14 | "https-proxy-agent": "^7.0.6", 15 | "node-fetch": "^3.3.2", 16 | "readline": "^1.3.0", 17 | "socks-proxy-agent": "^8.0.5", 18 | "winston": "^3.17.0", 19 | "ws": "^8.18.0" 20 | } 21 | } -------------------------------------------------------------------------------- /utils/banner.js: -------------------------------------------------------------------------------- 1 | const banner = `\n 2 | ███████╗██╗ ██╗ ██╗ ██████╗██╗ ██╗██████╗ ███████╗██████╗ 3 | ╚══███╔╝██║ ██║ ██╔╝ ██╔════╝╚██╗ ██╔╝██╔══██╗██╔════╝██╔══██╗ 4 | ███╔╝ ██║ █████╔╝ ██║ ╚████╔╝ ██████╔╝█████╗ ██████╔╝ 5 | ███╔╝ ██║ ██╔═██╗ ██║ ╚██╔╝ ██╔══██╗██╔══╝ ██╔══██╗ 6 | ███████╗███████╗██║ ██╗ ╚██████╗ ██║ ██████╔╝███████╗██║ ██║ 7 | ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ 8 | Running ExpChain Auto deploy CLI Version 9 | t.me/zlkcybergroup *** github.com/zlkcyber \n` 10 | 11 | export default banner; -------------------------------------------------------------------------------- /utils/logger.js: -------------------------------------------------------------------------------- 1 | import winston from 'winston'; 2 | 3 | const customTimestampFormat = winston.format((info) => { 4 | const timestamp = new Date().toLocaleString(); 5 | info.timestamp = `\x1b[36m${timestamp}\x1b[0m`; 6 | return info; 7 | }); 8 | 9 | const logFormat = winston.format.combine( 10 | customTimestampFormat(), 11 | winston.format.printf(({ timestamp, level, message }) => { 12 | if (message instanceof Error) { 13 | return `[ ${timestamp} ] [ ${level} ] ${message.stack || message.message}`; 14 | }; 15 | const coloredLevel = winston.format.colorize().colorize(level, level.toUpperCase()); 16 | return `[ ${timestamp} ] [ ${coloredLevel} ]: ${message}`; 17 | }) 18 | ); 19 | 20 | const logger = winston.createLogger({ 21 | level: 'info', 22 | format: logFormat, 23 | transports: [ 24 | new winston.transports.Console({ 25 | level: 'info', 26 | format: logFormat 27 | }), 28 | ] 29 | }); 30 | 31 | export default logger; 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2024] [zlkcyber] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AllStream Depin 2 | Mine Data, Fuel AI, Earn Rewards Join the Stream AI Revolution 3 | ![alt text](image-2.png) 4 | 5 | - Website [https://app.allstream.ai/](https://app.allstream.ai/index?referralCode=FlGQxaTO) 6 | - Twitter/X [@allstream_ai](https://x.com/allstream_ai) 7 | 8 | ## Features 9 | 10 | - **Auto Create Connections** 11 | - **Support Multy Accounts** 12 | - **Support Proxy** format `http://ip:port` or `http://username:password@ip:port` 13 | 14 | ## Requirements 15 | 16 | - **Node.js**: Ensure you have Node.js installed. 17 | - **NPM**: Ensure you have npm installed. 18 | - **AiStream ID**: follow instructions below to get 19 | - Create AiStream here : [https://app.allstream.ai/](https://app.allstream.ai/index?referralCode=FlGQxaTO) 20 | - F12 to inspect if you already login 21 | - find MyInfo from Network and copy your id. 22 | ![uid](image-1.png) 23 | 24 | 25 | ## Setup 26 | 27 | 1. Clone this repository: 28 | ```bash 29 | git clone https://github.com/Zlkcyber/streamAi.git 30 | cd streamAi 31 | ``` 32 | 2. Install dependencies: 33 | ```bash 34 | npm install 35 | ``` 36 | 3. Setup: Paste userId to `userIds.txt` 1 line 1 account 37 | ```bash 38 | nano userIds.txt 39 | ``` 40 | 4. Setup: paste proxy to `proxies.txt` 1 line 1 proxy 41 | ```bash 42 | nano proxies.txt 43 | ``` 44 | 5. Run The Script: 45 | ```bash 46 | npm run start 47 | ``` 48 | 49 | 50 | ## ![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg) 51 | 52 | This project is licensed under the [MIT License](LICENSE). 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /utils/scripts.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import log from './logger.js'; 3 | import { HttpsProxyAgent } from 'https-proxy-agent'; 4 | import { SocksProxyAgent } from 'socks-proxy-agent'; 5 | // Create an agent 6 | export const newAgent = (proxy = null) => { 7 | if (proxy) { 8 | if (proxy.startsWith('http://')) { 9 | return new HttpsProxyAgent(proxy); 10 | } else if (proxy.startsWith('socks4://') || proxy.startsWith('socks5://')) { 11 | return new SocksProxyAgent(proxy); 12 | } else { 13 | log.warn(`Unsupported proxy type: ${proxy}`); 14 | return null; 15 | } 16 | } 17 | return null; 18 | } 19 | 20 | export function loadFile(filePath) { 21 | try { 22 | const proxies = fs.readFileSync(filePath, 'utf8') 23 | .split('\n') 24 | .map(line => line.trim()) 25 | .filter(line => line.length > 0); 26 | return proxies; 27 | } catch (error) { 28 | log.error(`Failed to read file ${filePath}`); 29 | process.exit(0); 30 | } 31 | } 32 | 33 | export function loadProxies(filePath) { 34 | try { 35 | const proxies = fs.readFileSync(filePath, 'utf8') 36 | .split('\n') 37 | .map(line => line.trim()) 38 | .filter(line => line.length > 0); 39 | return proxies; 40 | } catch (error) { 41 | log.error(`Failed to read proxies running Without proxies...`); 42 | } 43 | } 44 | 45 | export function generateDeviceId() { 46 | const hexChars = '0123456789abcdef'; 47 | let deviceId = ''; 48 | for (let i = 0; i < 32; i++) { 49 | deviceId += hexChars[Math.floor(Math.random() * hexChars.length)]; 50 | } 51 | return deviceId; 52 | } 53 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import { generateDeviceId, loadProxies, loadFile } from './utils/scripts.js'; 2 | import { Gateway } from './utils/gateway.js'; 3 | import log from './utils/logger.js'; 4 | import banner from './utils/banner.js'; 5 | import fetch from 'node-fetch'; 6 | import { newAgent } from './utils/scripts.js'; 7 | 8 | 9 | const PROXIES_FILE = 'proxies.txt' 10 | const USERS_FILE = 'userIds.txt' 11 | const SERVER = "gw0.streamapp365.com"; 12 | const MAX_GATEWAYS = 32; 13 | 14 | async function dispatch(dev, user, proxy) { 15 | const agent = newAgent(proxy); 16 | try { 17 | const response = await fetch('https://dist.streamapp365.com/dispatch', { 18 | method: 'POST', 19 | headers: { 20 | 'Content-Type': 'application/json', 21 | }, 22 | body: JSON.stringify({ 23 | dev, 24 | user, 25 | }), 26 | agent: agent, 27 | }); 28 | 29 | if (!response.ok) { 30 | throw new Error('Network response was not ok'); 31 | } 32 | 33 | const data = await response.json(); 34 | return data; 35 | } catch (error) { 36 | return null; 37 | } 38 | } 39 | 40 | async function setupGatewaysForUser(user) { 41 | const proxies = loadProxies(PROXIES_FILE); 42 | const numberGateway = proxies.length > MAX_GATEWAYS ? MAX_GATEWAYS : proxies.length; 43 | const userGateways = []; 44 | let proxyIndex = 0; 45 | for (let i = 0; i < numberGateway; i++) { 46 | const proxy = proxies[proxyIndex]; 47 | proxyIndex = (proxyIndex + 1) % proxies.length; 48 | try { 49 | const deviceId = generateDeviceId(); 50 | log.info(`Connecting to Gateway ${i + 1} for User ${user} using Device ID: ${deviceId} via Proxy: ${proxy}`); 51 | 52 | const gateway = new Gateway(SERVER, user, deviceId, proxy); 53 | setInterval(() => dispatch(deviceId, user, proxy), 1000 * 60 * 1); 54 | userGateways.push(gateway); 55 | 56 | await new Promise((resolve) => setTimeout(resolve, 1000)); 57 | } catch (err) { 58 | log.error(`Failed to connect Gateway ${i + 1} for User ${user}: ${err.message}`); 59 | } 60 | } 61 | return userGateways; 62 | } 63 | 64 | async function main() { 65 | log.info(banner); 66 | const USERS = loadFile(USERS_FILE) 67 | try { 68 | log.info("Setting up gateways for all users..."); 69 | 70 | const results = await Promise.allSettled( 71 | USERS.map((user) => setupGatewaysForUser(user)) 72 | ); 73 | 74 | results.forEach((result, index) => { 75 | if (result.status === "fulfilled") { 76 | log.info(`User ${USERS[index]}: Successfully set up ${result.value.length} gateways.`); 77 | } else { 78 | log.error(`User ${USERS[index]}: Failed to set up gateways. Reason: ${result.reason}`); 79 | } 80 | }); 81 | 82 | log.info("All user gateway setups attempted."); 83 | 84 | process.on('SIGINT', () => { 85 | log.info("Cleaning up gateways..."); 86 | results 87 | .filter(result => result.status === "fulfilled") 88 | .flatMap(result => result.value) 89 | .forEach((gateway, index) => { 90 | if (gateway.ws) { 91 | log.info(`Closing Gateway ${index + 1}`); 92 | gateway.ws.close(); 93 | } 94 | }); 95 | process.exit(); 96 | }); 97 | 98 | } catch (error) { 99 | log.error("Unexpected error during gateway setup:", error); 100 | } 101 | } 102 | 103 | // Run 104 | main().catch((error) => log.error("Unexpected error:", error)); -------------------------------------------------------------------------------- /utils/gateway.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | import WebSocket from 'ws'; 3 | import log from './logger.js'; 4 | import { HttpsProxyAgent } from 'https-proxy-agent'; 5 | import { newAgent } from './scripts.js'; 6 | 7 | class Task { 8 | constructor(taskid, method, url, headers, body, script, debug, timeout, gateway, proxy = null) { 9 | this.proxy = proxy; 10 | this.agent = this.proxy ? newAgent(proxy) : null; 11 | this.taskid = taskid; 12 | this.controller = new AbortController(); 13 | this.born = Date.now(); 14 | this.timeout = timeout; 15 | this.gateway = gateway; 16 | 17 | const fetchOptions = { 18 | signal: this.controller.signal, 19 | method, 20 | headers, 21 | }; 22 | 23 | if (this.proxy) { 24 | fetchOptions.agent = this.agent; 25 | } 26 | 27 | if (body && method === "POST") { 28 | fetchOptions.body = body; 29 | } 30 | 31 | let statusCode = -1; 32 | 33 | this.task = fetch(url, fetchOptions) 34 | .then(async (response) => { 35 | const responseText = await response.text(); 36 | log.info(`Response: ${responseText}`); 37 | 38 | let parsedResult = ""; 39 | if (script && script.length > 0) { 40 | parsedResult = await GlobalExecutor.execute(script, responseText, this.timeout); 41 | } 42 | 43 | statusCode = response.status; 44 | 45 | if (response.ok) { 46 | this.gateway.transferResult(taskid, parsedResult, responseText, statusCode); 47 | } else { 48 | throw new CustomError(ERROR_CODES.NETWORK_ERROR, responseText); 49 | } 50 | }) 51 | .catch((error) => { 52 | log.error(`Task ${taskid} failed: ${error.message}`); 53 | this.gateway.transferError(taskid, error.message, error.code || DEFAULT_ERROR_CODE, statusCode); 54 | }) 55 | .finally(() => { 56 | log.info(`Task ${taskid} completed`); 57 | }); 58 | } 59 | 60 | cancel() { 61 | this.controller.abort(); 62 | } 63 | } 64 | 65 | 66 | class CustomError extends Error { 67 | constructor(code, message) { 68 | super(message); 69 | this.code = code; 70 | } 71 | } 72 | 73 | const MAX_CONNECTIONS = 32; 74 | const PING_INTERVAL = 20 * 1000; 75 | const CLEAR_INTERVAL = 30 * 1000; 76 | const CONNECTION_TIMEOUT = 300 * 1000; 77 | 78 | const ERROR_CODES = { 79 | NETWORK_ERROR: 50000, 80 | PARSE_SCRIPT_ERROR: 50001, 81 | PARSE_SCRIPT_TIMEOUT: 50002, 82 | PARSE_SCRIPT_RESULT_EMPTY: 50003, 83 | }; 84 | const DEFAULT_ERROR_CODE = ERROR_CODES.NETWORK_ERROR; 85 | 86 | class Gateway { 87 | constructor(server, user, dev, proxy = null) { 88 | this.proxy = proxy; 89 | this.agent = this.proxy ? newAgent(proxy) : null; 90 | this.server = server; 91 | this.user = user; 92 | this.dev = dev; 93 | this.proxy = proxy; 94 | this.isConnected = false; 95 | this.conns = new Map(); 96 | this.wsOptions = {}; 97 | 98 | if (this.proxy) { 99 | this.wsOptions.agent = this.agent; 100 | } 101 | 102 | this.ws = new WebSocket(`wss://${server}/connect`, this.wsOptions); 103 | this._setupWebSocket(); 104 | } 105 | 106 | _setupWebSocket() { 107 | this.ws.on("open", () => { 108 | log.info("Gateway connected."); 109 | this.isConnected = true; 110 | this._startPingInterval(); 111 | this.sendMessage( 112 | JSON.stringify({ 113 | type: "register", 114 | user: this.user, 115 | dev: this.dev, 116 | }) 117 | ); 118 | }); 119 | 120 | this.clearTimerId = setInterval(() => { 121 | const now = Date.now(); 122 | for (const [taskid, conn] of this.conns.entries()) { 123 | if (conn.born + CONNECTION_TIMEOUT < now) { 124 | conn.cancel(); 125 | log.info(`Task ${taskid} expired (born: ${conn.born}, now: ${now})`); 126 | } 127 | } 128 | }, CLEAR_INTERVAL); 129 | 130 | this.ws.on("message", (data) => { 131 | let messageString; 132 | if (Buffer.isBuffer(data)) { 133 | messageString = data.toString('utf8'); 134 | } else { 135 | messageString = data; 136 | } 137 | 138 | if (messageString === "pong") { 139 | log.info(`Device ID: [ \x1b[36m${this.dev}\x1b[0m ] Message: [ \x1b[36m${messageString}\x1b[0m ]`); 140 | return; 141 | } else { 142 | log.info(`Received message: ${messageString}`); 143 | } 144 | 145 | try { 146 | const message = JSON.parse(messageString); 147 | this._handleMessage(message); 148 | } catch (error) { 149 | log.error(`Error handling message: ${error.message}`); 150 | } 151 | }); 152 | 153 | this.ws.on("close", () => { 154 | log.info("Gateway disconnected."); 155 | this.isConnected = false; 156 | this._clearPingInterval(); 157 | this._reconnect(); 158 | }); 159 | 160 | this.ws.on("error", (error) => { 161 | log.error(`WebSocket error: ${error.message}`); 162 | }); 163 | } 164 | 165 | sendMessage(message) { 166 | if (this.ws.readyState === WebSocket.OPEN) { 167 | this.ws.send(message); 168 | } else { 169 | setTimeout(() => this.sendMessage(message), 1000); 170 | } 171 | } 172 | 173 | _startPingInterval() { 174 | if (!this.isConnected) return; 175 | this.timerId = setInterval(() => { 176 | try { 177 | if (this.isConnected) { 178 | this.sendMessage(JSON.stringify({ type: "ping" })); 179 | } 180 | } catch (error) { 181 | log.error(`Failed to send ping: ${error.message}`); 182 | } 183 | }, PING_INTERVAL); 184 | } 185 | 186 | _clearPingInterval() { 187 | if (this.timerId) { 188 | clearInterval(this.timerId); 189 | this.timerId = null; 190 | } 191 | } 192 | 193 | _handleMessage(message) { 194 | switch (message.type) { 195 | case "request": 196 | this._handleRequest(message); 197 | break; 198 | case "cancel": 199 | this._handleCancel(message.taskid); 200 | break; 201 | case "show": 202 | this._handleShow(); 203 | break; 204 | default: 205 | log.info(`Unexpected message type: ${message.type}`); 206 | } 207 | } 208 | 209 | _handleRequest(message) { 210 | const { taskid, data } = message; 211 | 212 | if (this.conns.size >= MAX_CONNECTIONS) { 213 | throw new Error("Connection limit exceeded."); 214 | } 215 | 216 | if (this.conns.has(taskid)) { 217 | throw new Error(`Duplicate connection for task ${taskid}`); 218 | } 219 | 220 | const { method = "GET", url = "", headers = {}, body = "", timeout = 30000, script = "" } = data; 221 | 222 | if (!url) { 223 | throw new Error("Request missing URL."); 224 | } 225 | 226 | if (!taskid) { 227 | throw new Error("Request missing task ID."); 228 | } 229 | 230 | log.info(`Handling task ${taskid}, URL: ${url}`); 231 | this.conns.set( 232 | taskid, 233 | new Task(taskid, method, url, headers, body, script, data.debug, timeout, this, this.proxy) 234 | ); 235 | } 236 | 237 | _handleCancel(taskid) { 238 | const connection = this.conns.get(taskid); 239 | if (connection) { 240 | connection.cancel(); 241 | this.conns.delete(taskid); 242 | } 243 | } 244 | 245 | _handleShow() { 246 | log.info("Active tasks:", Array.from(this.conns.keys())); 247 | } 248 | 249 | _reconnect() { 250 | setTimeout(() => { 251 | log.info("Reconnecting to gateway..."); 252 | this.ws = new WebSocket(`wss://${this.server}/connect`, this.wsOptions); 253 | this._setupWebSocket(); 254 | }, 3000); 255 | } 256 | 257 | transferResult(taskid, parsed, html, rawStatus) { 258 | const encodedHtmlContent = encodeURIComponent(html); 259 | const base64Encoded = btoa(encodedHtmlContent); 260 | const result = { 261 | type: "response", 262 | taskid, 263 | result: { parsed, html: base64Encoded, rawStatus }, 264 | }; 265 | log.info(`Sending result: ${JSON.stringify(result)}`); 266 | this.sendMessage(JSON.stringify(result)); 267 | this.conns.delete(taskid); 268 | } 269 | 270 | transferError(taskid, error, errorCode, rawStatus) { 271 | const errorResponse = { 272 | type: "error", 273 | taskid, 274 | error, 275 | errorCode, 276 | rawStatus, 277 | }; 278 | log.error(`Sending error: ${JSON.stringify(errorResponse)}`); 279 | this.sendMessage(JSON.stringify(errorResponse)); 280 | this.conns.delete(taskid); 281 | } 282 | } 283 | 284 | export { Gateway, Task, CustomError }; 285 | 286 | --------------------------------------------------------------------------------