agunq

ch.js

Jul 3rd, 2021 (edited)
2,018
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //made by agunq
  2. //this lib suck :d
  3. //you need to install ws and axios
  4. //npm install ws
  5. //npm install axios
  6. const WebSocket = require('ws');
  7. const EventEmitter = require('events');
  8. const Axios = require('axios');
  9.  
  10. function _getServer(group) {
  11.    
  12.     const tsweights = [['5', 75], ['6', 75], ['7', 75], ['8', 75], ['16', 75], ['17', 75], ['18', 75],
  13.                        ['9', 95], ['11', 95], ['12', 95], ['13', 95], ['14', 95], ['15', 95], ['19', 110],
  14.                        ['23', 110], ['24', 110], ['25', 110], ['26', 110], ['28', 104], ['29', 104],
  15.                        ['30', 104], ['31', 104], ['32', 104], ['33', 104], ['35', 101], ['36', 101],
  16.                        ['37', 101], ['38', 101], ['39', 101], ['40', 101], ['41', 101], ['42', 101],
  17.                        ['43', 101], ['44', 101], ['45', 101], ['46', 101], ['47', 101], ['48', 101],
  18.                        ['49', 101], ['50', 101], ['52', 110], ['53', 110], ['55', 110], ['57', 110],
  19.                        ['58', 110], ['59', 110], ['60', 110], ['61', 110], ['62', 110], ['63', 110],
  20.                        ['64', 110], ['65', 110], ['66', 110], ['68', 95], ['71', 116], ['72', 116],
  21.                        ['73', 116], ['74', 116], ['75', 116], ['76', 116], ['77', 116], ['78', 116],
  22.                        ['79', 116], ['80', 116], ['81', 116], ['82', 116], ['83', 116], ['84', 116]];
  23.  
  24.     group = group.replace('_', 'q').replace('-', 'q');
  25.  
  26.     const fnv = parseInt(group.slice(0, Math.min(group.length, 5)), 36);
  27.     let lnv = group.slice(6, 6 + Math.min(group.length - 5, 3));
  28.     if (lnv) {
  29.         lnv = parseInt(lnv, 36);
  30.         if (lnv < 1000) {
  31.             lnv = 1000;
  32.         }
  33.     }
  34.     else {
  35.         lnv = 1000;
  36.     }
  37.  
  38.     const num = (fnv % lnv) / lnv;
  39.     const sum = (arr=[]) => arr.reduce((total, val) => total + val);
  40.     const maxnum = sum(tsweights.map((n) => { return n[1]; }));
  41.     let cumfreq = 0;
  42.     for (let i = 0; i < tsweights.length; i++) {
  43.         const weight = tsweights[i];
  44.         cumfreq += weight[1] / maxnum;
  45.         if (num <= cumfreq) {
  46.             return `s${weight[0]}.chatango.com`;
  47.         }
  48.     }
  49.     const err_message = `Couldn't find host server for room ${group}`;
  50.    error(err_message);
  51.    throw new Error(err_message);
  52. }
  53.  
  54. function _strip_html(msg){
  55.    msg = msg.replace(/<\/?[^>]*>/g, "");
  56.    return msg;
  57. }
  58.  
  59. function _clean_message(msg){
  60.    
  61.    var n = msg.match(/<n(.*?)\/>/i);
  62.    if (n !== null){n = n[1]};
  63.    var f = msg.match(/<f(.*?)>/i);
  64.    if (f !== null){f = f[1]};
  65.    msg = msg.replace(/<n.*?\/>/g, "");
  66.    msg = msg.replace(/<f.*?>/g, "");
  67.    msg = _strip_html(msg);
  68.    msg = msg.replace(/&lt;/g, "<");
  69.    msg = msg.replace(/&gt;/g, ">");
  70.    msg = msg.replace(/&quot;/g, "\"");
  71.    msg = msg.replace(/&apos;/g, "'");
  72.    msg = msg.replace(/&amp;/g, "&");
  73.    return [msg, n, f];
  74. }
  75.  
  76. function _parseFont(f){
  77.    if (f !== null){
  78.        var [sizecolor, fontface] = f.split("=", 2);
  79.      
  80.        sizecolor = sizecolor.trim();
  81.        var size = sizecolor.match(/x(\d\d|\d)/i);
  82.        if (size !== null){
  83.            size = parseInt(size[1]);
  84.        }
  85.        else{size = 0}
  86.        var col = sizecolor.replace(/x(\d\d|\d)/i, "");
  87.        if (col === ""){col = "000"};
  88.        var face = fontface.slice(1,-1);
  89.        if (face === ""){face = "0"};
  90.        return [col, face, size];
  91.    }
  92.    else {
  93.        return ["000", "0", "10"];
  94.    }
  95.    
  96. }
  97.  
  98. function _genUid(){
  99.    var min = Math.pow(10, 15)
  100.    var max = Math.pow(10, 16)
  101.    var num = Math.floor(Math.random() * (max - min + 1)) + min;
  102.    return num.toString();
  103. }
  104.  
  105. function _getAnonId (n, ssid) {
  106.     if(!n || !ssid) return "";
  107.     var id = "";
  108.     for(var i=0; i<4; i++){
  109.         var a = parseInt(n.substr(i, 1)) + parseInt(ssid.substr(i+4, 1));
  110.         id += String(a>9 ? a-10 : a);
  111.     }
  112.     return id;
  113. }
  114.  
  115. const _users = {};
  116.  
  117. function User(name){
  118.    if (name.toLowerCase() in _users){
  119.        return _users[name.toLowerCase()];
  120.    }
  121.    else{
  122.        _users[name.toLowerCase()] = new _User(name);
  123.        return _users[name.toLowerCase()];
  124.    }
  125. }
  126.  
  127. class _User{
  128.    constructor(name) {
  129.        this.name = name;
  130.    }
  131. }
  132.  
  133. class Message{
  134.    constructor(text, time, user, ip = "", channel = "") {
  135.        this.time = time;
  136.        this.text = text;
  137.        this.user = user;
  138.        this.channel = channel;
  139.        this.ip = ip;
  140.    }
  141. }
  142.  
  143. class Room {
  144.    
  145.    constructor(mgr, name) {
  146.        this.mgr = mgr;
  147.        this.name = name;
  148.        this.server = _getServer(name);
  149.        this.port = 8081; // 8080 for ws://
  150.        this.ws = null;
  151.        this.firstCommand = true;
  152.        this.channel = "0"
  153.    }
  154.    
  155.    connect(){
  156.        const ws = new WebSocket(`wss://${this.server}:${this.port}`, {
  157.            origin: 'https://st.chatango.com'
  158.        });
  159.        ws.on('open', () => (this._connected()));
  160.        ws.on('close', () => (this._disconnected()));
  161.        ws.on('message', (data) => this.feed(data.toString()));
  162.        this.ws = ws
  163.    }
  164.    _auth(){
  165.        if (this.mgr.username !== "" & this.mgr.password !== ""){
  166.            this.sendCommand("bauth", this.name, _genUid(), this.mgr.username, this.mgr.password);
  167.        }
  168.        else{
  169.          
  170.            this.sendCommand("bauth", this.name, _genUid());
  171.        }
  172.    }
  173.    _connected () {
  174.        console.log('connected ' + this.name);
  175.        this._auth();
  176.        this._setPingInterval();
  177.    }
  178.    
  179.    _setPingInterval(){
  180.        this.pingInterval = setInterval(() => {
  181.            this.sendCommand("");
  182.            //console.log(`Ping at ${this.name}`);
  183.            }, 10000);
  184.    }
  185.    
  186.    _disconnected () {
  187.        clearInterval(this.pingInterval);
  188.        console.log('disconnected ' + this.name);
  189.    }
  190.    
  191.    disconnect(){
  192.        this.ws.close();
  193.    }
  194.    
  195.    feed(food){
  196.        //console.log(food.toString());
  197.        const [cmd, ...args] = food.split(":");
  198.        
  199.        const handler = this[`_rcmd_${cmd}`];
  200.        if (handler === undefined) {
  201.           //console.log(`Received command that has no handler from ${this.identifier}: <${cmd}>: ${args}`);
  202.        }
  203.        else {
  204.            handler.apply(this, args);
  205.        }
  206.    }
  207.    
  208.    sendCommand(...args){
  209.         if (this.firstCommand === true){
  210.             var terminator = "\x00";
  211.             this.firstCommand = false;
  212.        }
  213.         else {
  214.            var terminator = "\r\n\x00";
  215.        }
  216.        this.ws.send(args.join(":") + terminator);
  217.    }
  218.    
  219.    message(msg, html = false){
  220.        msg = String(msg);
  221.        if (html === false){
  222.                msg = msg.replace(/</g, "&lt;");
  223.                msg = msg.replace(/>/g, "&gt;");
  224.        }
  225.        msg = `<n${this.mgr.nameColor}/>` + msg
  226.        msg = `<f x${this.mgr.fontSize}${this.mgr.fontColor}="${this.mgr.fontFace}">` + msg
  227.        msg = msg.replace(/\n/g, "\r");
  228.        this.sendCommand("bm", "t12r", this.channel, msg);
  229.    }
  230.    
  231.    setBgMode(mode){
  232.        this.sendCommand("msgbg", mode.toString());
  233.    }
  234.    
  235.    _rcmd_i(...args){
  236.        var user = args[1];
  237.        var [msg, n, f] = _clean_message(args.slice(9).join(":"));
  238.        var [color, face, size] = _parseFont(f);
  239.    }
  240.    
  241.    _rcmd_b(...args){
  242.        //console.log(args);
  243.        var time = args[0];
  244.        var name = args[1];
  245.        var [msg, n, f] = _clean_message(args.slice(9).join(":"));
  246.        var [color, face, size] = _parseFont(f);
  247.        
  248.        if (name === ""){
  249.            name = "#" + args[2];
  250.            if (name === "#"){
  251.                name = "!anon" + _getAnonId(n, args[3]);
  252.            }
  253.        }
  254.        
  255.        var user = User(name);
  256.        var ip = args[6];
  257.        var channel = args[7];
  258.        this.channel = channel;
  259.        
  260.        msg = new Message(msg, time, user, ip, channel);
  261.        this.mgr.emit('Message', this, user, msg);
  262.    }
  263.    
  264.    _rcmd_u(...args){
  265.        
  266.    }
  267. }
  268.  
  269. class Private{
  270.    
  271.    constructor (mgr) {
  272.        this.mgr = mgr;
  273.        this.server = "c1.chatango.com";
  274.        this.port = 8081; // 8080 for ws://
  275.        this.ws = null;
  276.        this.firstCommand = true;
  277.    }
  278.    
  279.    connect(){
  280.        const ws = new WebSocket(`wss://${this.server}:${this.port}`, {
  281.            origin: 'https://st.chatango.com'
  282.        });
  283.        ws.on('open', () => (this._connected()));
  284.        ws.on('close', () => (this._disconnected()));
  285.        ws.on('message', (data) => this.feed(data.toString()));
  286.        this.ws = ws
  287.    }
  288.    
  289.    _auth(){
  290.        if (this.mgr.username !== "" & this.mgr.password !== ""){
  291.            
  292.            const response = Axios.get('https://chatango.com/login', {
  293.                params: {
  294.                    user_id: this.mgr.username,
  295.                    password: this.mgr.password,
  296.                    storecookie: "on",
  297.                    checkerrors: "yes"
  298.                }
  299.            })
  300.            
  301.            .then( (response) => {
  302.                var token = response["headers"]["set-cookie"].join("\n");
  303.                token = token.match(/auth\.chatango\.com ?= ?([^;]*)/);
  304.                if (token !== null){
  305.                    token = token[1];
  306.                    this.sendCommand("tlogin", token, "2");
  307.                }
  308.            })  
  309.        }
  310.    }
  311.    
  312.    _connected () {
  313.        console.log('connected PM');
  314.        this._auth();
  315.        this._setPingInterval();
  316.    }
  317.    
  318.    _setPingInterval(){
  319.        this.pingInterval = setInterval(() => {
  320.            this.sendCommand("");
  321.            //console.log("Ping at PM");
  322.            }, 10000);
  323.    }
  324.    
  325.    _disconnected () {
  326.        clearInterval(this.pingInterval);
  327.        console.log("disconnected PM");
  328.    }
  329.    
  330.    disconnect(){
  331.        this.ws.close();
  332.    }
  333.    
  334.    feed(food){
  335.        const [cmd, ...args] = food.replace("\r\n\u0000", "").split(":");
  336.        
  337.        const handler = this[`_rcmd_${cmd}`];
  338.        if (handler === undefined) {
  339.            //console.log(`Received command that has no handler from ${this.identifier}: <${cmd}>: ${args}`);
  340.        }
  341.        else {
  342.            handler.apply(this, args);
  343.        }
  344.    }
  345.    
  346.    sendCommand(...args){
  347.        if (this.firstCommand === true){
  348.            var terminator = "\x00";
  349.            this.firstCommand = false;
  350.        }
  351.        else {
  352.            var terminator = "\r\n\x00";
  353.        }
  354.        this.ws.send(args.join(":") + terminator);
  355.    }
  356.    
  357.    message(username, message){
  358.        if (username !== undefined || username !== null || message !== undefined || message !== null){
  359.            message = `<n${this.mgr.nameColor}/><m v="1"><g x${this.mgr.fontSize}s${this.mgr.fontColor}="${this.mgr.fontFace}">${message}</g></m>`
  360.            this.sendCommand("msg", username, message)
  361.        }
  362.    }
  363.    
  364.    _rcmd_OK(...args){
  365.        this.sendCommand("wl");
  366.        this.sendCommand("getblock");
  367.        this.sendCommand("getpremium", "1");
  368.    }
  369.    
  370.    _rcmd_msg(...args){
  371.        var user = User(args[0]);
  372.        var text = _strip_html(args.slice(5).join(":"));
  373.        var time = args[3];
  374.        var msg = new Message(text, time, user);
  375.        this.mgr.emit("PrivateMessage", this, user, msg);
  376.    }
  377.    
  378.    _rcmd_seller_name(...args){
  379.        //console.log(args);
  380.    }
  381.    
  382. }
  383.  
  384. class Chatango  extends EventEmitter {
  385.    constructor () {
  386.        super();
  387.        this.username = null;
  388.        this.password = null;
  389.      
  390.        this.nameColor = "000";
  391.        this.fontSize = 12;
  392.        this.fontFace = "0";
  393.        this.fontColor = "000";
  394.      
  395.        this.rooms = {};
  396.        //this.EV = new EventEmitter();
  397.    }
  398.    
  399.    easy_start(user, password, rooms){
  400.        this.username = user;
  401.        this.password = password;
  402.        this.PM = new Private(this);
  403.        this.PM.connect();
  404.        for (var i = 0; i < rooms.length; i++) {
  405.            this.joinRoom(rooms[i]);
  406.        }
  407.    }
  408.    
  409.    joinRoom(room){
  410.        this.rooms[room] = new Room(this, room);
  411.        this.rooms[room].connect();
  412.    }
  413.    
  414.    leaveRoom(room){
  415.        var room = this.rooms[room];
  416.        if (room !== undefined || room !== null){
  417.            room.disconnect();
  418.        }
  419.    }
  420.    
  421.    stop(){
  422.        for (const [ key, value ] of Object.entries(this.rooms)) {
  423.            value.disconnect();
  424.        }
  425.        this.PM.disconnect();
  426.    }
  427. }
  428.  
  429. exports.Chatango = Chatango;
  430.  
  431.  
Add Comment
Please, Sign In to add comment