Skip to main content
Loading...

More JavaScript Posts

//Retries maxRetries number of times, meaning that if you have 0, then it'll run the function once.
async function retryPromise(promiseFn, maxRetries = 3, delayOffset = 0, delayRandomRange = 0) {
	return new Promise((resolve, reject) => {
		promiseFn()
			.then(resolve, (error) => { //On error
				if (maxRetries <= 0) {
					return reject(error);
				} else {
					if(delayRandomRange * Math.random() + delayOffset < 1.0){
						return retryPromise(promiseFn, maxRetries - 1, delayOffset, delayRandomRange).then(resolve, reject);
					}else{
						return new Promise((resolveTwo, rejectTwo) => {
							setTimeout(() => {
								return retryPromise(promiseFn, maxRetries - 1, delayOffset, delayRandomRange).then(resolveTwo, rejectTwo);
							}, delayRandomRange * Math.random() + delayOffset);
						}).then(resolve, reject);
					}
				}
			});
	});
}

//Tests for that function.

//Returns a function that will fail numTimes times, then will return aValue
function functionThatReturnsAFunctionThatFailsACoupleTimes(numTimes, aValue){
	return async function(){
		if(numTimes == 0){
			return aValue;
		}
		numTimes--;
		throw false;
	};
}

const SMALL_NUMBER = 10;

function testTest(failNumberOfTimes){

	let functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(failNumberOfTimes, true);

	//Test my test
	for(let i = 0; i < (failNumberOfTimes * 2); ++i){
		function evalTest(val){
			let testTestFailedReason = "";
			if(val === undefined){
				testTestFailedReason = "Test test returned undefined for some reason.";
			}
			if((i + 1) > failNumberOfTimes){
				if(val === true){
					//We're good
				}else{
					testTestFailedReason = "Test test didn't return true when it should have.";
				}
			}else{
				if(val === false){
					//We're good
				}else{
					testTestFailedReason = "Test test didn't return false when it should have.";
				}
			}
			testTestFailedReason = testTestFailedReason || "Test test passed test case";
			console.log(testTestFailedReason, "at index", i, "where the function returned", val);
		}
		functionThatFailsACoupleTimes().then(evalTest, evalTest)
	};
}

testTest(SMALL_NUMBER);

let testCaseCounter = 1;

const throwsNoError = [
	(val)=>{
		if(val == true){
			console.log("Passed test case " + (testCaseCounter++));
		}else{
			console.error("Unexpected return value", val);
		}
	},
	()=>{
		console.error("It wasn't supposed to fail!")
	}
]

const throwsError = [
	(val)=>{
		console.error("It wasn't supposed to succeed!", val);
	},
	(val)=>{
		if(val == false){
			console.log("Passed test case " + (testCaseCounter++));
		}else{
			console.error("Unexpected return value", val);
		}
	}
];

//Runs SMALL_NUMBER times, because SMALL_NUMBER - 1 is the number of retries after the first one
let functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(SMALL_NUMBER - 1, true);

retryPromise(functionThatFailsACoupleTimes, SMALL_NUMBER - 1).then(...throwsNoError)

functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(SMALL_NUMBER - 1, true);

//Runs SMALL_NUMBER - 1 times, because SMALL_NUMBER - 2 is the number of retries after the first one
retryPromise(functionThatFailsACoupleTimes, SMALL_NUMBER - 2).then(...throwsError)

//Testing the delay. You'll have to wait a bit too.

functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(SMALL_NUMBER - 1, true);

//Runs SMALL_NUMBER times, because SMALL_NUMBER - 1 is the number of retries after the first one
retryPromise(functionThatFailsACoupleTimes, SMALL_NUMBER - 1, 500, 500).then(...throwsNoError)

functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(SMALL_NUMBER - 1, true);

//Runs SMALL_NUMBER - 1 times, because SMALL_NUMBER - 2 is the number of retries after the first one
retryPromise(functionThatFailsACoupleTimes, SMALL_NUMBER - 2, 500, 500).then(...throwsError)
class TreeNode {
  constructor(data, depth) {
    this.data = data;
    this.children = [];
    this.depth = depth;
  }
}

function buildNaryTree(hosts) {
  const nodeMap = {};

  // Step 1: Create a map of nodes using fqdn as the key
  hosts.forEach((host) => {
    nodeMap[host.fqdn] = new TreeNode(host, 0); // Initialize depth to 0
  });

  // Step 2: Iterate through the array and add each node to its parent's list of children
  hosts.forEach((host) => {
    if (host.displayParent) {
      if (nodeMap[host.displayParent]) {
        const parent = nodeMap[host.displayParent];
        const node = nodeMap[host.fqdn];
        node.depth = parent.depth + 1; // Update the depth
        parent.children.push(node);
      } else {
        console.error(`Parent with fqdn ${host.displayParent} not found for ${host.fqdn}`);
      }
    }
  });

  // Find the root nodes (nodes with no parent)
  const rootNodes = hosts.filter((host) => !host.displayParent).map((host) => nodeMap[host.fqdn]);

  return rootNodes;
}

function treeToObjects(node) {
  const result = [];

  function inOrder(node) {
    if (!node) {
      return;
    }

    
    // Visit the current node and add it to the result
    result.push(node.data);

    // Visit children nodes first
    node.children.forEach((child) => {
      inOrder(child);
    });
  }

  inOrder(node);
  return result;
}

// Usage example
const hosts = [
  {
    fqdn: 'fqdn_1',
    display_name: 'Host 1',
  },
  {
    fqdn: 'fqdn_2',
    display_name: 'Host 2',
    displayParent: 'fqdn_1',
  },
  {
    fqdn: 'fqdn_3',
    display_name: 'Host 3'
  },
  {
    fqdn: 'fqdn_4',
    display_name: 'Host 4',
    displayParent: 'fqdn_3',
  },
  {
    fqdn: 'fqdn_5',
    display_name: 'Host 5',
    displayParent: 'fqdn_1',
  },
];

const tree = buildNaryTree(hosts);

// Function to convert the tree to an array of objects
function convertTreeToArray(nodes) {
  const result = [];
  nodes.forEach((node) => {
    result.push(...treeToObjects(node));
  });
  return result;
}

// Convert the tree back to an array of objects
const arrayFromTree = convertTreeToArray(tree);

console.log(arrayFromTree);
const Discord = require('discord.js');
const client = new Discord.Client();
const token = 'YOUR_BOT_TOKEN';

// When the bot is ready, log a message to the console
client.on('ready', () => {
  console.log(`Logged in as ${client.user.tag}!`);
});

// When a user sends a message, check if they are authenticated
client.on('message', async (msg) => {
  if (!msg.author.bot && !msg.author.authenticated) {
    const filter = (m) => m.author.id === msg.author.id;
    const collector = msg.channel.createMessageCollector(filter, { time: 15000 });

    // Send an authentication message to the user
    msg.author.send('Please authenticate yourself by clicking this link: ' + generateAuthURL(msg.author.id));

    collector.on('collect', async (m) => {
      // Check if the message contains the authentication code
      if (m.content.startsWith('!auth ')) {
        const code = m.content.slice(6);
        const { access_token } = await getAccessToken(code);

        // Set the user's authenticated status and access token
        msg.author.authenticated = true;
        msg.author.access_token = access_token;
        collector.stop();
      }
    });

    collector.on('end', () => {
      if (!msg.author.authenticated) {
        msg.author.send('Authentication timed out.');
      }
    });
  }
});

// Generate an authentication URL for the user
function generateAuthURL(userId) {
  const redirectURI = encodeURIComponent('YOUR_REDIRECT_URL');
  const scopes = 'identify';
  const clientID = 'YOUR_CLIENT_ID';

  return `https://discord.com/api/oauth2/authorize?client_id=${clientID}&redirect_uri=${redirectURI}&response_type=code&scope=${scopes}&state=${userId}`;
}

// Exchange the authorization code for an access token
async function getAccessToken(code) {
  const redirectURI = encodeURIComponent('YOUR_REDIRECT_URL');
  const clientID = 'YOUR_CLIENT_ID';
  const clientSecret = 'YOUR_CLIENT_SECRET';

  const res = await fetch('https://discord.com/api/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: `grant_type=authorization_code&code=${code}&redirect_uri=${redirectURI}&client_id=${clientID}&client_secret=${clientSecret}`,
  });

  return await res.json();
}

client.login(token);
//Disclaimer: I do not condone mass web scraping of ESPN websites, and this is just theoretical code that hasn't been used.

//Scrape player stats off of https://www.espn.com/nfl/team/roster/_/name/phi/philadelphia-eagles

//Example player JS object
/*
{
	"shortName": "S. Opeta",
	"name": "Sua Opeta",
	"href": "http://www.espn.com/nfl/player/_/id/3121009/sua-opeta",
	"uid": "s:20~l:28~a:3121009",
	"guid": "dec19157-e984-f981-3724-498281328c97",
	"id": "3121009",
	"height": "6' 4\"",
	"weight": "305 lbs",
	"age": 27,
	"position": "G",
	"jersey": "78",
	"birthDate": "08/15/96",
	"headshot": "https://a.espncdn.com/i/headshots/nfl/players/full/3121009.png",
	"lastName": "Sua Opeta",
	"experience": 4,
	"college": "Weber State"
}
*/

//The page needs to be focused, so you have to put this code in a bookmarklet and click the page before clicking it. Allegedly.
navigator.clipboard.writeText(JSON.stringify(
    window["__espnfitt__"].page.content.roster.groups.flatMap((group)=>{
        return group.athletes.map((athlete)=>{
            //We can assume all football players are above 100 lbs and below 1000 lbs.
            athlete.weight = parseInt(athlete.weight.substring(0,3));
            
            if(athlete.experience == "R") athlete.experience = 0;
            else athlete.experience = parseInt(athlete.experience);

            //We can assume players are at least 1 foot, or under 10 feet tall.
            athlete.inches = 12 * parseInt(athlete.height.substring(0, 1)); //Add feet in inches
            athlete.inches += parseInt(athlete.height.substring(2).replaceAll("\"", "").trim()); //Add remaining inches

            const monthDayYear = athlete.birthDate.split("/");
            athlete.birthMonth = parseInt(monthDayYear[0]);
            athlete.birthDay = parseInt(monthDayYear[1]);
            athlete.birthYear = parseInt(monthDayYear[2]);
            
            //The only really useful stuff we get from this is Height, weight, left handedness, age, position, and birthday
            return athlete;
        });
    })
, null, "\t")).then(null, ()=>{alert("That failed.")});

//Changes all the team links on this page https://www.espn.com/nfl/stats/team to the team's roster for easier scraping
$$("table > tbody > tr > td > div > div > a").forEach((elm)=>{
	elm.setAttribute("href", elm.getAttribute("href").replace("team/", "team/roster/"));
});