Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Fred a betting master 🎲🎲🎲 #21

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Changes proposed in this pull request:

-
-
-

Description of user interaction with new changes:

-
-
-

Fixes #

- [ ] I have updated the readme to include the new command(s) (If necessary)
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
The fam has moved to Discord so we are reincarnating Fred to Discord as well

Fred's abilities include:
* Ping
* Replies "Pong"
* Pubsub
* Replies with a version of yes or no to whether or not pub subs are on sale


- Ping
- Replies "Pong"
- Pubsub
- Replies with a version of yes or no to whether or not pub subs are on sale
- Image (search term)
- Replies with an image from google image search of the specified search term
- Animate (search term)
- Replies with an animated image from google image search of the specified search term
- Where
- Replies with the hostname of the machine fred is running from

Fred's future abilities:
* Roll X (Where x is a number)
* Replies with a random number between 0-X
* Image X (where x is any search term)
* Replies with a google image result

- Roll X (Where x is a number)
- Replies with a random number between 0-X
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"start": "node ./output/index.js",
"dev": "nodemon ./output/index.js",
"format": "prettier --write ./src",
"build": "tsc"
"build": "tsc",
"build:watch": "tsc --watch"
},
"dependencies": {
"@types/node-fetch": "^2.5.7",
Expand Down
39 changes: 39 additions & 0 deletions src/commands/imageSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Discord from "discord.js";
import { searchId, googleToken } from "../config.json";
import fetch from "node-fetch";

/**
* Initiates a google image search on specified term and responds with a link to the image
* @param {Discord.Messaage} message
*/
export function imageSearch(message: Discord.Message): Promise<void> {
var searchTerm = message.content.split(" ");
searchTerm = searchTerm.splice(2);
var formattedsearch = searchTerm.join("%20");
var num = Math.floor(Math.random() * 10);
var type =
message.content.split(" ")[1] == "animate" ? "&imgType=animated" : "";
// Search parameters at https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list
return fetch(
"https://www.googleapis.com/customsearch/v1?key=" +
googleToken +
"&cx=" +
searchId +
"&searchType=image" +
type +
"&q=" +
formattedsearch
)
.then((res) => res.json())
.then((data) => {
message.channel.send(
"search term: " + searchTerm.join(" ") + " \n" + data.items[num].link
);
})
.catch((error) => {
console.log(error);
message.channel.send(
"Shits broke, Im not fixing it. probably. <@116415248935682049>"
);
});
}
3 changes: 3 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

export * from "./ping";
export * from "./pubSub";
export * from "./imageSearch";
export * from "./location";
export * from "./roll";
11 changes: 11 additions & 0 deletions src/commands/location.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Discord from "discord.js";

/**
* Responds to "where" with the host name of the machine Fred is running on
* @param message
*/
export function location(message: Discord.Message) {
const os = require("os");
const hostname = os.hostname();
return message.channel.send(hostname);
}
2 changes: 1 addition & 1 deletion src/commands/pubSub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function pubSub(message: Discord.Message): Promise<void> {
}
})
.catch((error) => {
console.log(error);
console.error(error);
message.channel.send("Shits broke, Im not fixing it. probably.");
});
}
115 changes: 115 additions & 0 deletions src/commands/roll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import Discord from "discord.js";

const command = "roll";

/**
* The possible named result groups from the RegEx
*/
type RollRegexGroup = {
wow?: string;
lo?: string;
hi?: string;
dnd?: string;
n?: string;
d?: string;
};

/**
* Rolls a dice given the correct format
* @param message
*/
export function roll(message: Discord.Message) {
// Make this a promise because we are dealing with math and RegEx which, if abused, could take long.
return new Promise((resolve) => {
const messageText = message.content.toLowerCase();

// Extract the values we want and run the RegEx to parse input.
const commandArguments = messageText
.substr(messageText.indexOf(command) + command.length + 1)
.match(rollRegex);

// If there is no match, we get null
if (commandArguments) {
if (commandArguments.groups?.wow !== undefined) {
// If our match is a WoW one, it behaves as \roll in WoW
const { wow, lo, hi } = commandArguments.groups as RollRegexGroup;

/** Lower boundary. Default 1 */
const lowerBoundary = Number(lo ?? 1);
/** Upper boundary. Default 100 */
const upperBoundary = Number(hi ?? 100);

const roll =
Math.floor(Math.random() * (upperBoundary - lowerBoundary + 1)) +
lowerBoundary;

if (!Number.isSafeInteger(roll)) {
// If our math yielded something that isn't a number
// Maybe because the input includes really large numbers
resolve(
message.channel.send(
`${message.author.toString()} Sorry, I can't roll for that input: ${wow}`
)
);
} else {
// Math worked out, notifying user about the result
resolve(
message.channel.send(
`${message.author.toString()} rolls **${roll}** (${lowerBoundary}-${upperBoundary})`
)
);
}
} else if (commandArguments.groups?.dnd !== undefined) {
// If our match is a DnD one, treat this as a single dice roll with no modifier.
const { dnd, n, d } = commandArguments.groups as RollRegexGroup;

/** Number of dice to be rolled. Default 1 */
const numberOfDice = Number(n ?? 1);
/** The maximum number to roll. Not optional, but I am tired and TS understands that it may be undefined. */
const sidesOfDice = Number(d ?? 20);

// Make sure we can do math with the numbers given.
// If we can't, tel the user
if (
numberOfDice > 10000 ||
!Number.isSafeInteger(numberOfDice * sidesOfDice)
) {
resolve(
message.channel.send(
`${message.author.toString()} Sorry, I can't roll that high! I mean, maybe I can, but I really don't want to: ${dnd}`
)
);
// I don't think the Promise should reject since the process worked as intended in successfully rejecting faulty input
// But maybe we need a way to notify the parent that that was the case?
// return reject("Cannot calculate that roll: " + dnd);
} else {
// Calculate the dice rolls
let roll = 0;
for (let dice = 0; dice < Number(numberOfDice); dice++) {
roll += Math.floor(Math.random() * Number(sidesOfDice) + 1);
}
// Respond to user to inform the result of the roll
resolve(
message.channel.send(
`${message.author.toString()} rolls **${roll}** (${numberOfDice}d${sidesOfDice})`
)
);
}
}
} else {
// Regex did not match, therefore we cannot roll
resolve(
message.channel.send(
message.author.toString() +
" Sorry, I cannot roll for that; it did not match the RegEx."
)
);
// See comment a few lines above, search for `return reject`
// return reject(...)
}
});
}

// Will match dice rolls and wow rolls
// Thank yo Adam for the RegEx! https://regex101.com/r/LG2LyO/1
const rollRegex = /^(?:(?<wow>(?<lo>\d+\s+)?(?<hi>\d+)?)|(?<dnd>(?<n>\d+)d(?<d>\d+)))$/;
29 changes: 28 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Discord from "discord.js";
import { prefix, token } from "./config.json";
import { pubSub, ping } from "./commands";
import { pubSub, ping, imageSearch, location, roll } from "./commands";

const client = new Discord.Client();

Expand All @@ -23,6 +23,17 @@ client.on("message", (message) => {
//Are they on sale?
pubSub(message);
break;
case "image":
case "animate":
imageSearch(message);
break;
case "where":
location(message);
break;
case "roll":
// Roll dice
roll(message);
break;
}
} else if (message.channel.type === "dm") {
var args = lowerMessage.split(" ");
Expand All @@ -33,10 +44,26 @@ client.on("message", (message) => {
ping(message);
break;
case "pubsub":
//Are they on sale?
pubSub(message);
break;
case "image":
case "animate":
imageSearch(message);
break;
case "where":
location(message);
break;
case "roll":
// Roll dice
roll(message);
break;
}
}
});

client.on("error", (err) => {
console.error(err);
});

client.login(token);