mirror of
https://github.com/ION606/selmerBot.git
synced 2026-05-14 21:26:54 +00:00
Added the 'stocks' command
This commit is contained in:
@@ -10,7 +10,7 @@ const tutoText = [
|
||||
"__**AMIME AND MANGA**__\nGet info on your favorite Anime or Manga as a stat-sheet, a fancy embed, or have Selmer Bot describe it to you!\n\n__***COMMANDS***__\n!asearch, !msearch",
|
||||
"__**GAMES**__\nAt the moment Selmer Bot only offers two games: Trivia and Tic Tac Toe. Both games can be played with other people, but only Trivia can be played solo. Selmer Bot also has a battle game where you can use weapons, potions, attack and defend, but this is still in beta\n\n__***COMMANDS***__\n!help game, !game battle !game tictactoe, !game trivia, !game equip, !game status, !game hp, !game classes, !game quit",
|
||||
"__**SELMER SPECIFIC**__\nThese commands will probably be found nowhere else!\nThese include quotes (For legal reasons I have to state they aren't real quotes, mostly), as well as varius other things I based on good old Selmer\n\n__***COMMANDS***__\n!arrow, !extracredit, !tuto, !profile, !quotes",
|
||||
"__**MISCELLANEOUS**__\nThese are the commands that are not really in any of the other categories. Don't be fooled, these are actually some of the most useful commands Selmer Bot has to offer. From playing music to web scraping to memes, I'm sure Selmer Bot has what you're looking for!\n\n__***COMMANDS***__\n!help, !kareoke, !link, !meme, !pickupline, !audio, !react, !scrape",
|
||||
"__**MISCELLANEOUS**__\nThese are the commands that are not really in any of the other categories. Don't be fooled, these are actually some of the most useful commands Selmer Bot has to offer. From playing music to web scraping to memes, I'm sure Selmer Bot has what you're looking for!\n\n__***COMMANDS***__\n!help, !kareoke, !link, !meme, !pickupline, !audio, !react, !scrape, !stocks",
|
||||
"__**DM COMMANDS**__\nThese commands will only work in DM's. All these commands will only work with Selmer Bot Premium (it's on the next page).\nThese features include Reminders (AKA a calendar) and Selmer Bot's own chat AI!\n\n__***COMMANDS***__\n!chat, !startconvo, !endconvo, !premium",
|
||||
"__**SELMER BOT PREMIUM**__\nUse an AI chat, complete with semi-accurate IRL data, have Selmer Bot remind you of events with an easy-to-use interface and even a clickable calendar on the Selmer Bot website (_www.selmerbot.com_)\n\n__***COMMANDS***__\n!premium, !premium buy, !premium manage, !reminders",
|
||||
"__**Thank you for completing the Selmer Bot Tutorial!**__\n\nTry out all Selmer Bot's features, play the games and most importantly, have fun!\n\n-The Selmer Bot Team AKA ION606"
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
const { Modal, TextInputComponent, MessageActionRow, MessageButton, MessageEmbed, Interaction } = require('discord.js');
|
||||
|
||||
const dateFns = require('date-fns');
|
||||
const { formatToTimeZone } = require('date-fns-timezone');
|
||||
const Alpaca = require('@alpacahq/alpaca-trade-api');
|
||||
const apiKeyId = require('../../config.json').alpKey;
|
||||
const secretKey = require('../../config.json').alpSec;
|
||||
const alpaca = new Alpaca({
|
||||
keyId: apiKeyId,
|
||||
secretKey: secretKey,
|
||||
paper: true,
|
||||
usePolygon: false
|
||||
});
|
||||
|
||||
//This is the same as making the following request: https://data.alpaca.markets/v2/stocks/snapshots?symbols={stock_symbols_here}
|
||||
async function getStockData(bot, message, args, stock) {
|
||||
try {
|
||||
const snapshotPromise = alpaca.getSnapshot(stock);
|
||||
|
||||
snapshotPromise.then(snapshot => {
|
||||
const embd = new MessageEmbed()
|
||||
.setAuthor({ name: "Selmer Bot", url: "", iconURL: bot.user.displayAvatarURL() })
|
||||
.setFooter({ text: 'Selmer Bot uses Alpaca for stock information'})
|
||||
|
||||
if (args[1] == 'trade') {
|
||||
const lt = snapshot.LatestTrade;
|
||||
embd.setTitle(`${stock} Latest Trade`)
|
||||
.setTimestamp(lt.Timestamp)
|
||||
.addFields(
|
||||
{name: 'Price', value: `${lt.Price}`},
|
||||
{name: 'Size', value: `${lt.Size}`},
|
||||
|
||||
//This will always be IEX, as it is the only exchange the free version offers
|
||||
{name: 'Exchange', value: `IEX (${lt.Exchange})`},
|
||||
)
|
||||
} else if (args[1] == 'quote') {
|
||||
if (args[2] == 'after') {
|
||||
return message.reply("Due to the markets not being open, there is no quote data available!");
|
||||
}
|
||||
const lq = snapshot.LatestQuote;
|
||||
embd.setTitle(`${stock} Latest Quote`)
|
||||
.setTimestamp(lq.Timestamp)
|
||||
.addFields(
|
||||
{name: 'Ask Price', value: `${lq.AskPrice}`},
|
||||
{name: 'Ask Size', value: `${lq.AskSize}`},
|
||||
{name: 'Bid price', value: `${lq.BidPrice}`},
|
||||
{name: 'Bid Size', value: `${lq.BidSize}`},
|
||||
|
||||
//This will always be IEX, as it is the only exchange the free version offers
|
||||
{name: 'Exchange', value: `IEX (${lq.Exchange})`},
|
||||
)
|
||||
} else if (args[1] == 'bars') {
|
||||
const mb = snapshot.MinuteBar;
|
||||
const db = snapshot.DailyBar;
|
||||
const pdb = snapshot.PrevDailyBar;
|
||||
embd.setTitle(`${stock} Bars`)
|
||||
.setTimestamp(mb.Timestamp)
|
||||
.addFields(
|
||||
{name: 'Minute Bar', value: `Open Price: ${mb.OpenPrice},\nClose Price: ${mb.ClosePrice},\nHigh Price: ${mb.HighPrice},\nLow Price: ${mb.LowPrice},\nVolume: ${mb.Volume},\nCount: ${mb.TradeCount},\nVWAP: ${mb.VWAP}`},
|
||||
{name: 'Day Bar (Today)', value: `Open Price: ${db.OpenPrice},\nClose Price: ${db.ClosePrice},\nHigh Price: ${db.HighPrice},\nLow Price: ${db.LowPrice},\nVolume: ${db.Volume},\nCount: ${db.TradeCount},\nVWAP: ${db.VWAP}`},
|
||||
{name: 'Day Bar (Yesterday)', value: `Open Price: ${pdb.OpenPrice},\nClose Price: ${pdb.ClosePrice},\nHigh Price: ${pdb.HighPrice},\nLow Price: ${pdb.LowPrice},\nVolume: ${pdb.Volume},\nCount: ${pdb.TradeCount},\nVWAP: ${pdb.VWAP}`},
|
||||
)
|
||||
} else {
|
||||
return message.reply("The command format is: _!stocks <stock_name, 'hours'> <trade, quote, bars> [after]_");
|
||||
}
|
||||
|
||||
message.reply({embeds: [embd]});
|
||||
})
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
message.reply("Uh Oh, there's been an error!");
|
||||
}
|
||||
}
|
||||
|
||||
function getData(bot, message, args) {
|
||||
var stock;
|
||||
if (args.length < 1) {
|
||||
return message.reply("Please specify a stock (ex: AAPL, GOOG, etc)")
|
||||
} else { stock = args[0];}
|
||||
|
||||
|
||||
const format = `yyyy-MM-dd HH:mm:ss`;
|
||||
const date = dateFns.format(new Date(), format);
|
||||
|
||||
alpaca.getClock().then((clock) => {
|
||||
// var txt = `The market is currently ${clock.is_open ? 'open.' : 'closed.'}`;
|
||||
|
||||
alpaca.getCalendar({
|
||||
start: date,
|
||||
end: date
|
||||
}).then((calendars) => {
|
||||
let temp;
|
||||
if (clock.is_open || args[2] == 'after') {
|
||||
if (args[0] == 'hours') {
|
||||
temp = `The markets opened at ${calendars[0].open} and will close at ${calendars[0].close} on ${date}.`;
|
||||
return message.reply(temp);
|
||||
}
|
||||
getStockData(bot, message, args, stock);
|
||||
} else {
|
||||
// `The market is currently ${clock.is_open ? 'open.' : 'closed.'}`
|
||||
//May be innacurate?
|
||||
temp = `_The markets closed at \`${calendars[0].close}\` and will open again at \`${calendars[0].open}\` on \`${dateFns.format((new Date()).setDate(new Date().getDate() + 1), 'yyyy-MM-dd')}\`.\nTo get the last snapshot before market closure, add the \`after\` keyword to the end of your command (trade and bars ONLY), ex: !stocks GOOG bars after_`;
|
||||
return message.reply(temp);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//!stocks <stock_name, "hours"> <trade, quote, bars> [after]
|
||||
module.exports = {
|
||||
name: 'stocks',
|
||||
description: "Have Selmer Bot give you \"current\" stock prices",
|
||||
async execute(message, args, Discord, Client, bot) {
|
||||
if (args[0] == 'help' || args.length < 1) {
|
||||
return message.reply("The command format is: _!stocks <stock_name, 'hours'> <trade, quote, bars> [after]_");
|
||||
}
|
||||
getData(bot, message, args);
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ if (process.env.token != undefined) {
|
||||
|
||||
MLAIKEY = require('./config.json').MLAIKEY;
|
||||
StripeAPIKey = require('./config.json').StripeAPIKey;
|
||||
|
||||
// { token, home_server, debug_channel, MLAIKEY, StripeAPIKey } = require('./config.json'); // Doesn't work
|
||||
IDM = true;
|
||||
}
|
||||
|
||||
Generated
+732
-52
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@alpacahq/alpaca-trade-api": "^2.16.1",
|
||||
"@discordjs/opus": "github:discordjs/opus",
|
||||
"@discordjs/rest": "^1.0.1",
|
||||
"@discordjs/voice": "^0.8.0",
|
||||
@@ -9,6 +10,8 @@
|
||||
"axios": "^0.27.2",
|
||||
"canvas": "^2.9.3",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"date-fns": "^2.29.2",
|
||||
"date-fns-timezone": "^0.1.4",
|
||||
"discord-reply": "^0.1.2",
|
||||
"discord.js": "^13.6.0",
|
||||
"feedparser": "^2.2.10",
|
||||
@@ -26,6 +29,7 @@
|
||||
"play-dl": "^1.9.4",
|
||||
"random-memes": "^3.1.0",
|
||||
"request": "^2.88.2",
|
||||
"robinhood": "^1.8.0",
|
||||
"rss-parser": "^3.12.0",
|
||||
"sequelize": "^6.19.0",
|
||||
"sqlite3": "^5.0.3",
|
||||
|
||||
Reference in New Issue
Block a user