clean redundant api endpoints
This commit is contained in:
parent
4823333017
commit
82e574955e
@ -1,24 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/all-strategies', async (request, reply) => {
|
||||
const data = request.body;
|
||||
const userId = data?.userId;
|
||||
let output;
|
||||
|
||||
try {
|
||||
output = await pb.collection("stockscreener").getFullList({
|
||||
filter: `user="${userId}"`,
|
||||
});
|
||||
}
|
||||
catch(e) {
|
||||
output = [];
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -7,16 +7,10 @@ const cors = require("@fastify/cors");
|
||||
require("dotenv").config({ path: "../app/.env" });
|
||||
const fmpAPIKey = process.env.FMP_API_KEY;
|
||||
//const mixpanelAPIKey = process.env.MIXPANEL_API_KEY;
|
||||
const twitchAPIKey = process.env.TWITCH_API_KEY;
|
||||
const twitchSecretKey = process.env.TWITCH_SECRET_KEY;
|
||||
|
||||
//const Mixpanel = require('mixpanel');
|
||||
//const UAParser = require('ua-parser-js');
|
||||
|
||||
const got = require("got"); //Only version npm i got@11.8.3 works with ESM
|
||||
const cheerio = require("cheerio");
|
||||
const sharp = require("sharp");
|
||||
const axios = require("axios");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
//const pino = require('pino');
|
||||
@ -60,37 +54,9 @@ const corsMiddleware = (request, reply, done) => {
|
||||
};
|
||||
fastify.addHook("onRequest", corsMiddleware);
|
||||
|
||||
//fastify.register(require('./mixpanel/server'), { mixpanel, UAParser });
|
||||
fastify.register(require("./get-post/server"), { pb });
|
||||
fastify.register(require("./get-one-post/server"), { pb });
|
||||
fastify.register(require("./get-portfolio-data/server"), { pb });
|
||||
fastify.register(require("./create-portfolio/server"), { pb, serialize });
|
||||
fastify.register(require("./buy-stock/server"), { pb });
|
||||
fastify.register(require("./sell-stock/server"), { pb });
|
||||
fastify.register(require("./create-post-link/server"), { got, cheerio, sharp });
|
||||
fastify.register(require("./create-post-image/server"), { sharp });
|
||||
fastify.register(require("./delete-comment/server"), { pb });
|
||||
fastify.register(require("./delete-post/server"), { pb });
|
||||
fastify.register(require("./leaderboard/server"), { pb });
|
||||
fastify.register(require("./edit-name-watchlist/server"), { pb });
|
||||
fastify.register(require("./create-strategy/server"), { pb });
|
||||
fastify.register(require("./delete-strategy/server"), { pb });
|
||||
fastify.register(require("./all-strategies/server"), { pb });
|
||||
fastify.register(require("./save-strategy/server"), { pb });
|
||||
fastify.register(require("./get-strategy/server"), { pb });
|
||||
fastify.register(require("./get-twitch-status/server"), {
|
||||
axios,
|
||||
twitchAPIKey,
|
||||
twitchSecretKey,
|
||||
});
|
||||
fastify.register(require("./get-portfolio/server"), { pb });
|
||||
fastify.register(require("./create-price-alert/server"), { pb });
|
||||
|
||||
fastify.register(require("./get-price-alert/server"), { pb, fs, path });
|
||||
fastify.register(require("./delete-price-alert/server"), { pb });
|
||||
fastify.register(require("./upvote/server"), { pb });
|
||||
fastify.register(require("./downvote/server"), { pb });
|
||||
fastify.register(require("./upvote-comment/server"), { pb });
|
||||
fastify.register(require("./downvote-comment/server"), { pb });
|
||||
|
||||
|
||||
//fastify.register(require('./create-comment/server'), { pb });
|
||||
|
||||
|
||||
@ -1,140 +0,0 @@
|
||||
// Declare a route
|
||||
|
||||
|
||||
function processHoldingsList(holdings) {
|
||||
const stockGroups = {};
|
||||
|
||||
for (const stock of holdings) {
|
||||
if (stock.symbol in stockGroups) {
|
||||
stockGroups[stock.symbol].totalCost += stock.boughtPrice * stock.numberOfShares;
|
||||
stockGroups[stock.symbol].totalShares += stock.numberOfShares;
|
||||
} else {
|
||||
stockGroups[stock.symbol] = {
|
||||
totalCost: stock.boughtPrice * stock.numberOfShares,
|
||||
totalShares: stock.numberOfShares,
|
||||
name: stock.name,
|
||||
assetType: stock.assetType,
|
||||
currentPrice: stock.currentPrice,
|
||||
dailyChange: stock.dailyChange,
|
||||
sinceBoughtChange: stock.sinceBoughtChange,
|
||||
};
|
||||
}
|
||||
|
||||
// Update dailyChange automatically
|
||||
stockGroups[stock.symbol].dailyChange = stock.dailyChange;
|
||||
stockGroups[stock.symbol].sinceBoughtChange = stock.sinceBoughtChange;
|
||||
stockGroups[stock.symbol].currentPrice = stock.currentPrice;
|
||||
}
|
||||
|
||||
const updatedHoldings = [];
|
||||
|
||||
for (const symbol in stockGroups) {
|
||||
const { totalCost, totalShares, name, assetType, currentPrice, dailyChange, sinceBoughtChange } = stockGroups[symbol];
|
||||
const finalBoughtPrice = totalCost / totalShares;
|
||||
const updatedStock = {
|
||||
symbol,
|
||||
name,
|
||||
assetType,
|
||||
boughtPrice: finalBoughtPrice,
|
||||
currentPrice,
|
||||
dailyChange,
|
||||
sinceBoughtChange: Number(((currentPrice/finalBoughtPrice -1) * 100)?.toFixed(2)),
|
||||
numberOfShares: totalShares,
|
||||
};
|
||||
updatedHoldings.push(updatedStock);
|
||||
}
|
||||
|
||||
return updatedHoldings;
|
||||
}
|
||||
|
||||
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/buy-stock', async (request, reply) => {
|
||||
|
||||
const holidays = ['2024-01-01', '2024-01-15','2024-02-19','2024-03-29','2024-05-27','2024-06-19','2024-07-04','2024-09-02','2024-11-28','2024-12-25'];
|
||||
const currentDate = new Date().toISOString().split('T')[0];
|
||||
|
||||
// Get the current time in the ET time zone
|
||||
const etTimeZone = 'America/New_York';
|
||||
const currentTime = new Date().toLocaleString('en-US', { timeZone: etTimeZone });
|
||||
|
||||
// Determine if the NYSE is currently open or closed
|
||||
const currentHour = new Date(currentTime).getHours();
|
||||
const isWeekend = new Date(currentTime).getDay() === 6 || new Date(currentTime).getDay() === 0;
|
||||
const isBeforeMarketOpen = currentHour < 9 || (currentHour === 9 && new Date(currentTime).getMinutes() < 30);
|
||||
const isAfterMarketClose = currentHour >= 16;
|
||||
|
||||
const isStockMarketOpen = !(isWeekend || isBeforeMarketOpen || isAfterMarketClose || holidays?.includes(currentDate));
|
||||
let output;
|
||||
if (isStockMarketOpen === true) {
|
||||
|
||||
const data = request.body;
|
||||
const currentDate = new Date();
|
||||
const year = currentDate.getFullYear();
|
||||
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is zero-based
|
||||
const day = '01';
|
||||
|
||||
const formattedDate = `${year}-${month}-${day}`; // Output: "yyyy-mm-01"
|
||||
|
||||
const userId = data?.userId;
|
||||
|
||||
let newHolding = {'symbol': data['symbol'],
|
||||
'name': data['name'],
|
||||
'assetType': data['assetType'],
|
||||
'numberOfShares': data['numberOfShares'],
|
||||
'boughtPrice': data['boughtPrice'],
|
||||
'currentPrice': data['boughtPrice'],
|
||||
'dailyChange': 0,
|
||||
'sinceBoughtChange': 0 }
|
||||
|
||||
let currentPortfolio = await pb.collection("portfolios").getList(1, 500, {
|
||||
filter: `user="${userId}" && created >="${formattedDate}" `,
|
||||
});
|
||||
|
||||
currentPortfolio = currentPortfolio?.items[0];
|
||||
|
||||
let holdings = currentPortfolio?.holdings || [];
|
||||
|
||||
let tradingHistory = currentPortfolio?.tradingHistory || [];
|
||||
|
||||
let availableCash = currentPortfolio?.availableCash - data['estimatedTotal'];
|
||||
|
||||
holdings.push(newHolding)
|
||||
|
||||
const updatedHoldings = processHoldingsList(holdings)
|
||||
|
||||
|
||||
tradingHistory.push({'symbol': data['symbol'],
|
||||
'name': data['name'],
|
||||
'assetType': data['assetType'],
|
||||
'numberOfShares': data['numberOfShares'],
|
||||
'price': Number(data['boughtPrice']),
|
||||
'type': 'buy',
|
||||
'date': new Date()});
|
||||
|
||||
try {
|
||||
|
||||
await pb.collection("portfolios").update(currentPortfolio?.id, {
|
||||
"holdings": updatedHoldings,
|
||||
"availableCash": availableCash,
|
||||
"tradingHistory": tradingHistory,
|
||||
})
|
||||
output = 'success';
|
||||
|
||||
} catch (err) {
|
||||
output = 'failure'
|
||||
}
|
||||
}
|
||||
else {
|
||||
output = 'marketClosed'
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
})
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
const serialize = opts.serialize;
|
||||
|
||||
fastify.post('/create-portfolio', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
|
||||
const formData = {'user': data?.userId, 'accountValue': 100000,
|
||||
'availableCash': 100000, 'overallReturn': 0, 'rank': 0,
|
||||
'holdings': JSON.stringify([]), 'tradingHistory': '[]',
|
||||
'metrics': JSON.stringify({'alpha': 'n/a',
|
||||
'beta': 'n/a',
|
||||
'maxDrawdown': 0
|
||||
})
|
||||
}
|
||||
let output = 'failure';
|
||||
try {
|
||||
await pb.collection('portfolios').create(serialize(formData));
|
||||
output = 'success';
|
||||
}
|
||||
catch(e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
|
||||
|
||||
reply.send({ message: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,39 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
const sharp = opts.sharp;
|
||||
|
||||
fastify.post('/create-post-image', async (request, reply) => {
|
||||
try {
|
||||
const data = request.body;
|
||||
let imageBufferArray = data?.imageBufferArray;
|
||||
|
||||
|
||||
if (imageBufferArray) {
|
||||
// Resize and optimize the image
|
||||
const optimizedImageBuffer = await sharp(imageBufferArray)
|
||||
.resize({
|
||||
width: 800,
|
||||
height: 1000,
|
||||
fit: sharp.fit.inside,
|
||||
withoutEnlargement: true,
|
||||
})
|
||||
.jpeg({ quality: 80 })
|
||||
.toBuffer();
|
||||
|
||||
|
||||
|
||||
// Send the optimized image in the response
|
||||
reply.send({
|
||||
image: optimizedImageBuffer,
|
||||
});
|
||||
} else {
|
||||
reply.status(400).send({ error: 'Image data is missing.' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error processing image:', error);
|
||||
reply.status(500).send({ error: 'Internal Server Error' });
|
||||
}
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,77 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
const got = opts.got;
|
||||
const cheerio = opts.cheerio;
|
||||
const sharp = opts.sharp;
|
||||
|
||||
fastify.post('/create-post-link', async (request, reply) => {
|
||||
const data = request.body;
|
||||
const url = data?.link;
|
||||
let description;
|
||||
let imageBuffer;
|
||||
|
||||
try {
|
||||
const response = await got(url, {
|
||||
headers: {
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
|
||||
},
|
||||
responseType: 'buffer',
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.body);
|
||||
|
||||
description = $('head meta[property="og:description"]').attr('content');
|
||||
let image = $('head meta[property="og:image"]').attr('content');
|
||||
|
||||
if (!image) {
|
||||
let largestSize = 0;
|
||||
let largestImage = '';
|
||||
|
||||
$('img').each(async function () {
|
||||
if ($(this).attr('src') && $(this).attr('src').match(/\.(webp|jpg|jpeg|png|gif)$/)) {
|
||||
try {
|
||||
imageBuffer = await got($(this).attr('src'), {
|
||||
headers: {
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
|
||||
},
|
||||
responseType: 'buffer',
|
||||
}).then((response) => response.body);
|
||||
|
||||
const metadata = await sharp(imageBuffer).metadata();
|
||||
const imageSize = metadata.width * metadata.height;
|
||||
|
||||
if (imageSize > largestSize) {
|
||||
largestSize = imageSize;
|
||||
largestImage = $(this).attr('src');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error getting image:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
image = largestImage;
|
||||
}
|
||||
|
||||
imageBuffer = await got(image, {
|
||||
headers: {
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
|
||||
},
|
||||
responseType: 'buffer',
|
||||
}).then((response) => response.body);
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
// Check if imageBlob is not null before sending it in the response
|
||||
reply.send({
|
||||
description: description,
|
||||
image: imageBuffer,
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
// Declare a route
|
||||
|
||||
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/create-price-alert', async (request, reply) => {
|
||||
|
||||
const data = request.body;
|
||||
|
||||
let output;
|
||||
|
||||
let newAlert = {
|
||||
'user': data['userId'],
|
||||
'symbol': data['symbol']?.toUpperCase(),
|
||||
'name': data['name'],
|
||||
'assetType': data['assetType']?.toLowerCase(),
|
||||
'targetPrice': Number(data['targetPrice']),
|
||||
'condition': data['condition']?.toLowerCase(),
|
||||
'priceWhenCreated': Number(data['priceWhenCreated']),
|
||||
'triggered': false,
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
|
||||
await pb.collection("priceAlert")?.create(newAlert)
|
||||
output = 'success';
|
||||
|
||||
} catch (err) {
|
||||
output = 'failure'
|
||||
}
|
||||
|
||||
|
||||
reply.send({ items: output })
|
||||
})
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/create-strategy', async (request, reply) => {
|
||||
const data = request.body;
|
||||
let output;
|
||||
|
||||
try {
|
||||
output = await pb.collection("stockscreener").create(data)
|
||||
}
|
||||
catch(e) {
|
||||
output = {};
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,48 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/delete-comment', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
let output;
|
||||
const userId = data?.userId;
|
||||
const commentUserId = data?.commentUser;
|
||||
const commentId = data.commentId
|
||||
|
||||
//Each delete gives the user -1 Karma points
|
||||
|
||||
let checkModerator = await pb.collection('moderators').getList(1, 50)
|
||||
|
||||
//OP and moderators have the right to delete comments
|
||||
if (commentUserId === userId || checkModerator.items.some((item) => item.user === userId))
|
||||
{
|
||||
|
||||
try {
|
||||
|
||||
await pb.collection('comments').delete(commentId);
|
||||
await pb.collection("users").update(commentUserId, {
|
||||
"karma-": 1,
|
||||
})
|
||||
|
||||
output = 'success';
|
||||
|
||||
|
||||
} catch (err) {
|
||||
output = 'failure'
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
else {
|
||||
output = 'failure';
|
||||
}
|
||||
|
||||
|
||||
|
||||
reply.send({ message: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,40 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/delete-post', async (request, reply) => {
|
||||
const data = request.body;
|
||||
const postId = data?.postId;
|
||||
const userId = data?.userId;
|
||||
const moderator = 'db5s41oatgoeh0q' //moderators can always delete post
|
||||
let output;
|
||||
|
||||
try {
|
||||
if(moderator === userId)
|
||||
{
|
||||
await pb.collection('posts').delete(postId);
|
||||
output = 'success';
|
||||
}
|
||||
else {
|
||||
const res = await pb.collection('posts').getOne(postId);
|
||||
if (res?.user === userId)
|
||||
{
|
||||
await pb.collection('posts').delete(postId);
|
||||
output = 'success';
|
||||
}
|
||||
else {
|
||||
output = 'failure';
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
console.log(e)
|
||||
output = 'failure';
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,26 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/delete-price-alert', async (request, reply) => {
|
||||
const data = request.body;
|
||||
const priceAlertIdList = data?.priceAlertIdList;
|
||||
let output;
|
||||
try {
|
||||
for (const item of priceAlertIdList) {
|
||||
await pb.collection("priceAlert")?.delete(item)
|
||||
}
|
||||
output = 'success';
|
||||
}
|
||||
catch(e) {
|
||||
//console.log(e)
|
||||
output = 'failure';
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/delete-strategy', async (request, reply) => {
|
||||
const data = request.body;
|
||||
let output;
|
||||
|
||||
try {
|
||||
await pb.collection("stockscreener").delete(data['strategyId'])
|
||||
output = 'success';
|
||||
}
|
||||
catch(e) {
|
||||
output = 'failure';
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,187 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/downvote-comment', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
const commentId = data?.commentId;
|
||||
const userId = data?.userId;
|
||||
|
||||
let output = 'failure';
|
||||
|
||||
console.log(data)
|
||||
|
||||
|
||||
try {
|
||||
|
||||
let doesUserExist = await pb.collection("alreadyVoted").getList(1, 50, {
|
||||
filter: `user="${userId}"` && `comment="${commentId}"`,
|
||||
})
|
||||
|
||||
doesUserExist = doesUserExist?.items?.find(item => item?.user === userId && item?.comment === commentId);
|
||||
//console.log('Does it exist yet: ', doesUserExist)
|
||||
|
||||
const votedId = doesUserExist?.id;
|
||||
let currentVote = doesUserExist?.type;
|
||||
|
||||
const opPost = await pb.collection('comments').getOne(commentId)
|
||||
|
||||
console.log('currentVote: ', currentVote)
|
||||
/*
|
||||
console.log('commentId: ', commentId)
|
||||
console.log('votedId: ', votedId)
|
||||
console.log('currentVote: ', currentVote)
|
||||
console.log('user: ', user);
|
||||
*/
|
||||
|
||||
//If user has no history with this post create it
|
||||
if( !currentVote || votedId === 'undefined')
|
||||
{
|
||||
console.log('created')
|
||||
let formDataAlreadyVoted = new FormData();
|
||||
formDataAlreadyVoted.append('post', commentId);
|
||||
formDataAlreadyVoted.append('user', userId);
|
||||
formDataAlreadyVoted.append('notifyType', 'downvote');
|
||||
await pb.collection('alreadyVoted').create(formDataAlreadyVoted);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (currentVote === 'upvote')
|
||||
{
|
||||
|
||||
|
||||
await pb.collection("comments").update(commentId, {
|
||||
"downvote+": 1,
|
||||
});
|
||||
|
||||
await pb.collection("comments").update(commentId, {
|
||||
"upvote-": 1,
|
||||
});
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'downvote',
|
||||
});
|
||||
|
||||
|
||||
//if user is the opPost then it should only subtract -1 once
|
||||
let opPost = await pb.collection('comment').getOne(commentId)
|
||||
|
||||
if (opPost.user === userId)
|
||||
{
|
||||
//Punishment: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 2,
|
||||
})
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Punishment: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 2,
|
||||
})
|
||||
|
||||
//Punishment: User who downvotes post also loose -1 karma points
|
||||
await pb.collection("users").update(userId, {
|
||||
"karma-": 2,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (currentVote === 'neutral' || !currentVote)
|
||||
{
|
||||
|
||||
if (opPost.user === userId)
|
||||
{
|
||||
//Punishment: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 1,
|
||||
})
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Punishment: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 1,
|
||||
})
|
||||
|
||||
//Punishment: User who downvotes post also loose -1 karma points
|
||||
await pb.collection("users").update(userId, {
|
||||
"karma-": 1,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
await pb.collection("comments").update(commentId, {
|
||||
"downvote+": 1,
|
||||
});
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'downvote',
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
await pb.collection("comments").update(commentId, {
|
||||
"downvote-": 1,
|
||||
});
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'neutral',
|
||||
});
|
||||
|
||||
|
||||
let opPost = await pb.collection('comment').getOne(commentId)
|
||||
|
||||
//if user is the opPost then it should only add +1 once
|
||||
if (opPost.user === userId)
|
||||
{
|
||||
//Reset Punishment: Find user of post and add +1 karma points back
|
||||
let opPost = await pb.collection('comment').getOne(commentId)
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma+": 1,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Reset Punishment: Find user of post and add +1 karma points back
|
||||
let opPost = await pb.collection('comment').getOne(commentId)
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma+": 1,
|
||||
})
|
||||
|
||||
//Reset Punishment: User who removes downvote gets back +1 karma points
|
||||
await pb.collection("users").update(userId, {
|
||||
"karma+": 1,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch(e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
|
||||
reply.send({ items: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,186 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/downvote', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
const postId = data?.postId;
|
||||
const userId = data?.userId;
|
||||
|
||||
let output = 'failure';
|
||||
|
||||
|
||||
try {
|
||||
|
||||
let doesUserExist = await pb.collection("alreadyVoted").getList(1, 50, {
|
||||
filter: `user="${userId}"` && `post="${postId}"`,
|
||||
})
|
||||
|
||||
doesUserExist = doesUserExist.items.find(item => item.user === userId && item.post === postId);
|
||||
//console.log('Does it exist yet: ', doesUserExist)
|
||||
|
||||
const votedId = doesUserExist?.id;
|
||||
let currentVote = doesUserExist?.type;
|
||||
|
||||
const opPost = await pb.collection('posts').getOne(postId)
|
||||
|
||||
//console.log('currentVote: ', currentVote)
|
||||
|
||||
/*
|
||||
console.log('postId: ', postId)
|
||||
console.log('votedId: ', votedId)
|
||||
console.log('currentVote: ', currentVote)
|
||||
console.log('user: ', user);
|
||||
*/
|
||||
|
||||
//If user has no history with this post create it
|
||||
if( !currentVote || votedId === 'undefined')
|
||||
{
|
||||
|
||||
let formDataAlreadyVoted = new FormData();
|
||||
formDataAlreadyVoted.append('post', postId);
|
||||
formDataAlreadyVoted.append('user', userId);
|
||||
formDataAlreadyVoted.append('type', 'downvote');
|
||||
await pb.collection('alreadyVoted').create(formDataAlreadyVoted);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (currentVote === 'upvote')
|
||||
{
|
||||
|
||||
|
||||
await pb.collection("posts").update(postId, {
|
||||
"downvote+": 1,
|
||||
});
|
||||
|
||||
await pb.collection("posts").update(postId, {
|
||||
"upvote-": 1,
|
||||
});
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'downvote',
|
||||
});
|
||||
|
||||
|
||||
//if user is the opPost then it should only subtract -1 once
|
||||
let opPost = await pb.collection('posts').getOne(postId)
|
||||
|
||||
if (opPost.user === userId)
|
||||
{
|
||||
//Punishment: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 2,
|
||||
})
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Punishment: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 2,
|
||||
})
|
||||
|
||||
//Punishment: User who downvotes post also loose -1 karma points
|
||||
await pb.collection("users").update(userId, {
|
||||
"karma-": 2,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (currentVote === 'neutral' || !currentVote)
|
||||
{
|
||||
|
||||
if (opPost.user === userId)
|
||||
{
|
||||
//Punishment: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 1,
|
||||
})
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Punishment: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 1,
|
||||
})
|
||||
|
||||
//Punishment: User who downvotes post also loose -1 karma points
|
||||
await pb.collection("users").update(userId, {
|
||||
"karma-": 1,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
await pb.collection("posts").update(postId, {
|
||||
"downvote+": 1,
|
||||
});
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'downvote',
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
await pb.collection("posts").update(postId, {
|
||||
"downvote-": 1,
|
||||
});
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'neutral',
|
||||
});
|
||||
|
||||
|
||||
let opPost = await pb.collection('posts').getOne(postId)
|
||||
|
||||
//if user is the opPost then it should only add +1 once
|
||||
if (opPost.user === userId)
|
||||
{
|
||||
//Reset Punishment: Find user of post and add +1 karma points back
|
||||
let opPost = await pb.collection('posts').getOne(postId)
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma+": 1,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Reset Punishment: Find user of post and add +1 karma points back
|
||||
let opPost = await pb.collection('posts').getOne(postId)
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma+": 1,
|
||||
})
|
||||
|
||||
//Reset Punishment: User who removes downvote gets back +1 karma points
|
||||
await pb.collection("users").update(userId, {
|
||||
"karma+": 1,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch(e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
|
||||
reply.send({ items: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,29 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/edit-name-watchlist', async (request, reply) => {
|
||||
const data = request.body;
|
||||
const watchListId = data?.watchListId;
|
||||
const newTitle = data?.title;
|
||||
|
||||
let output;
|
||||
|
||||
try {
|
||||
await pb.collection("watchlist").update(watchListId, {
|
||||
'title': newTitle
|
||||
})
|
||||
output = 'success';
|
||||
}
|
||||
catch(e) {
|
||||
//console.log(e)
|
||||
output = 'failure';
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,22 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/get-one-post', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
const postId = data?.postId;
|
||||
|
||||
const output = await pb.collection('posts').getOne(postId, {
|
||||
expand: 'user,alreadyVoted(post)',
|
||||
fields: "*,expand.user,expand.alreadyVoted(post).user,expand.alreadyVoted(post).type"
|
||||
|
||||
});
|
||||
|
||||
reply.send({ items: output })
|
||||
})
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/get-portfolio-data', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
const userId = data?.userId
|
||||
|
||||
const currentDate = new Date();
|
||||
|
||||
const year = currentDate.getFullYear();
|
||||
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is zero-based
|
||||
const day = '01';
|
||||
|
||||
const formattedDate = `${year}-${month}-${day}`; // Output: "yyyy-mm-01"
|
||||
|
||||
|
||||
//Get Portfolio of user for current month
|
||||
const output = await pb.collection("portfolios").getList(1, 500, {
|
||||
filter: `user="${userId}" && created >="${formattedDate}" `,
|
||||
});
|
||||
|
||||
reply.send({ items: output.items })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,36 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/get-portfolio', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
const userId = data?.userId;
|
||||
// Get the current date
|
||||
const currentMonth = new Date();
|
||||
const nextMonth = new Date(currentMonth);
|
||||
nextMonth.setDate(currentMonth.getDate() + 31); // Add a number of days to ensure next month
|
||||
|
||||
// Set the day to 1 to get the beginning of the current month
|
||||
const beginningOfMonth = new Date(currentMonth);
|
||||
beginningOfMonth.setDate(1);
|
||||
|
||||
const beginningOfNextMonth = new Date(nextMonth);
|
||||
beginningOfNextMonth.setDate(1);
|
||||
|
||||
// Format it as a string if needed
|
||||
const startDate = beginningOfMonth.toISOString().split('T')[0];
|
||||
const endDate = beginningOfNextMonth.toISOString().split('T')[0];
|
||||
|
||||
//console.log('Start Date:', startDate);
|
||||
//console.log('End Date:', endDate);
|
||||
|
||||
const output = await pb.collection("portfolios").getFullList(query_params = {"filter": `user="${userId}" && created >= "${startDate}" && created < "${endDate}"`})
|
||||
|
||||
reply.send({ items: output })
|
||||
})
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
@ -1,171 +0,0 @@
|
||||
// Optimized postHotness function
|
||||
function postHotness(upvotes, created) {
|
||||
let s = 0;
|
||||
for (let i = 1; i <= upvotes; i++) {
|
||||
if (i <= 3) {
|
||||
s += 1;
|
||||
} else if (i <= 6) {
|
||||
s += 3;
|
||||
} else if (i <= 10) {
|
||||
s += 3;
|
||||
} else if (i <= 20) {
|
||||
s += 4;
|
||||
} else if (i <= 40) {
|
||||
s += 5;
|
||||
} else {
|
||||
s += 6;
|
||||
}
|
||||
}
|
||||
|
||||
const order = Math.log10(Math.max(Math.abs(s), 1));
|
||||
let sign = 0;
|
||||
if (s > 0) {
|
||||
sign = 1;
|
||||
} else if (s < 0) {
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
const interval = 45000; // or 69000
|
||||
const createdDate = new Date(created);
|
||||
const seconds = createdDate.getTime() / 1000;
|
||||
const hotness = order + (sign * seconds) / interval;
|
||||
return Math.round(hotness * 10000000);
|
||||
}
|
||||
|
||||
module.exports = function (fastify, opts, done) {
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post("/get-post", async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
let filter;
|
||||
const sort = data?.sortingPosts === "hot" ? "-upvote" : "-created";
|
||||
let pinnedPost;
|
||||
let posts;
|
||||
|
||||
try {
|
||||
if (data?.seenPostId.length !== 0) {
|
||||
filter = data?.seenPostId?.map((id) => `id!="${id}"`).join("&&");
|
||||
|
||||
//applies only for profile and user directory
|
||||
if (data?.userId) {
|
||||
filter += `&& user="${data?.userId}" && pinned=false`;
|
||||
}
|
||||
|
||||
if (data?.filterTicker) {
|
||||
filter += `&& tagline="${data?.filterTicker}" && pinned=false`;
|
||||
}
|
||||
|
||||
if (data?.sortingPosts === "hot") {
|
||||
//community page code space
|
||||
// In case of sort === 'hot' show the most recent post up to 7 week by ranking them with the function postHotness
|
||||
|
||||
let endDate = new Date();
|
||||
// Get the date one week earlier
|
||||
let startDate = new Date();
|
||||
startDate.setDate(endDate.getDate() - 180);
|
||||
endDate.setDate(endDate.getDate() + 1);
|
||||
|
||||
// Format the dates as needed (e.g., "YYYY-MM-DD")
|
||||
let endDateStr = endDate.toISOString().split("T")[0];
|
||||
let startDateStr = startDate.toISOString().split("T")[0];
|
||||
|
||||
filter += `&& created >= "${startDateStr}" && created <= "${endDateStr}" && pinned = false`;
|
||||
}
|
||||
|
||||
posts = (
|
||||
await pb.collection("posts").getList(data?.startPage, 10, {
|
||||
sort: "-created",
|
||||
filter: filter,
|
||||
expand: "user,comments(post),alreadyVoted(post)",
|
||||
fields:
|
||||
"*,expand.user,expand.comments(post), expand.alreadyVoted(post).user,expand.alreadyVoted(post).type",
|
||||
})
|
||||
)?.items;
|
||||
|
||||
if (data?.sortingPosts === "hot") {
|
||||
// Add hotness property to each post
|
||||
posts?.forEach((post) => {
|
||||
post.hotness = postHotness(post?.upvote, post?.created);
|
||||
});
|
||||
posts?.sort((a, b) => b?.hotness - a?.hotness);
|
||||
}
|
||||
} else {
|
||||
if (data?.userId) {
|
||||
posts = (
|
||||
await pb.collection("posts").getList(data?.startPage, 10, {
|
||||
sort: sort,
|
||||
filter: `user="${data?.userId}" && pinned=false`,
|
||||
expand: `user,comments(post),alreadyVoted(post)`,
|
||||
fields:
|
||||
"*,expand.user,expand.comments(post), expand.alreadyVoted(post).user,expand.alreadyVoted(post).type",
|
||||
})
|
||||
)?.items;
|
||||
} else if (data?.filterTicker) {
|
||||
posts = await pb.collection("posts").getList(data?.startPage, 10, {
|
||||
sort: sort,
|
||||
filter: `tagline="${data?.filterTicker}" && pinned=false`,
|
||||
expand: `user,comments(post),alreadyVoted(post)`,
|
||||
fields:
|
||||
"*,expand.user,expand.comments(post), expand.alreadyVoted(post).user,expand.alreadyVoted(post).type",
|
||||
});
|
||||
} else {
|
||||
//community page code space
|
||||
// In case of sort === 'hot' show the most recent post up to 7 week by ranking them with the function postHotness
|
||||
|
||||
if (data?.sortingPosts === "hot") {
|
||||
let endDate = new Date();
|
||||
// Get the date one week earlier
|
||||
let startDate = new Date();
|
||||
startDate.setDate(endDate.getDate() - 30);
|
||||
endDate.setDate(endDate.getDate() + 1);
|
||||
|
||||
// Format the dates as needed (e.g., "YYYY-MM-DD")
|
||||
let endDateStr = endDate.toISOString().split("T")[0];
|
||||
let startDateStr = startDate.toISOString().split("T")[0];
|
||||
|
||||
filter = `created >= "${startDateStr}" && created <= "${endDateStr}" && pinned = false`;
|
||||
} else {
|
||||
filter = `pinned=false`;
|
||||
}
|
||||
posts = await pb.collection("posts").getList(1, 10, {
|
||||
sort: "-created",
|
||||
filter: filter,
|
||||
expand: "user, comments(post), alreadyVoted(post)",
|
||||
fields:
|
||||
"*,expand.user,expand.comments(post), expand.alreadyVoted(post).user,expand.alreadyVoted(post).type",
|
||||
});
|
||||
|
||||
posts = posts.items;
|
||||
// Add hotness property to each post
|
||||
if (data?.sortingPosts === "hot") {
|
||||
posts?.forEach((post) => {
|
||||
post.hotness = postHotness(post?.upvote, post?.created);
|
||||
});
|
||||
|
||||
posts?.sort((a, b) => b?.hotness - a?.hotness);
|
||||
}
|
||||
|
||||
pinnedPost = await pb.collection("posts").getFullList({
|
||||
filter: `pinned=true`,
|
||||
sort: "-created",
|
||||
expand: `user,comments(post),alreadyVoted(post)`,
|
||||
fields:
|
||||
"*,expand.user,expand.comments(post), expand.alreadyVoted(post).user,expand.alreadyVoted(post).type",
|
||||
});
|
||||
|
||||
for (let i = pinnedPost?.length - 1; i >= 0; i--) {
|
||||
posts?.unshift(pinnedPost[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
//console.log(e)
|
||||
posts = [];
|
||||
}
|
||||
|
||||
reply.send({ items: posts });
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,21 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/get-strategy', async (request, reply) => {
|
||||
const data = request.body;
|
||||
let output;
|
||||
|
||||
try {
|
||||
output = await pb.collection("stockscreener").getOne(data['strategyId'])
|
||||
}
|
||||
catch(e) {
|
||||
output = {};
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,49 +0,0 @@
|
||||
module.exports = function (fastify, opts, done) {
|
||||
const axios = opts.axios;
|
||||
const twitchAPIKey = opts.twitchAPIKey;
|
||||
const twitchSecretKey = opts.twitchSecretKey;
|
||||
|
||||
fastify.get('/get-twitch-status', async (request, reply) => {
|
||||
let twitchStatus = false;
|
||||
|
||||
const client_id = twitchAPIKey;
|
||||
const client_secret = twitchSecretKey;
|
||||
const streamer_name = 'stocknear';
|
||||
|
||||
try {
|
||||
// Obtain an access token from Twitch
|
||||
|
||||
const tokenResponse = await axios.post('https://id.twitch.tv/oauth2/token', null, {
|
||||
params: {
|
||||
client_id,
|
||||
client_secret,
|
||||
grant_type: 'client_credentials',
|
||||
},
|
||||
});
|
||||
|
||||
const { access_token } = tokenResponse.data;
|
||||
|
||||
// Check if the stream is online
|
||||
const streamResponse = await axios.get(
|
||||
`https://api.twitch.tv/helix/streams?user_login=${streamer_name}`,
|
||||
{
|
||||
headers: {
|
||||
'Client-ID': client_id,
|
||||
Authorization: `Bearer ${access_token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const streamData = streamResponse.data;
|
||||
twitchStatus = streamData.data.length === 1;
|
||||
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
reply.send({ items: twitchStatus });
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,31 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/leaderboard', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
const startDate = data?.startDate;
|
||||
const endDate = data?.endDate;
|
||||
let output;
|
||||
|
||||
try {
|
||||
output = await pb.collection("portfolios").getFullList({
|
||||
filter: `created >= "${startDate}" && created < "${endDate}"`,
|
||||
expand: 'user'
|
||||
})
|
||||
|
||||
}
|
||||
catch(e) {
|
||||
//console.log(e)
|
||||
output = []
|
||||
}
|
||||
|
||||
|
||||
reply.send({ items: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,72 +0,0 @@
|
||||
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const mixpanel = opts.mixpanel;
|
||||
const UAParser = opts.UAParser;
|
||||
|
||||
fastify.post('/mixpanel', async (request, reply) => {
|
||||
|
||||
const data = request.body;
|
||||
|
||||
const { browser, cpu, device, os } = UAParser(data.userAgent)
|
||||
|
||||
let options = {
|
||||
path: data.path,
|
||||
browser: browser.name,
|
||||
browser_version: browser.version,
|
||||
device: device.vendor,
|
||||
cpu: cpu.architecture,
|
||||
os: os.name,
|
||||
}
|
||||
|
||||
|
||||
if (data.type === 'trackPageError')
|
||||
{
|
||||
options.status = data.status;
|
||||
options.message = data.message;
|
||||
mixpanel.track('Error status', options);
|
||||
console.log('Send error page data to mixpanel')
|
||||
}
|
||||
|
||||
else if (data.type === 'trackPageVisit')
|
||||
{
|
||||
mixpanel.track('Page Visit', options);
|
||||
|
||||
}
|
||||
|
||||
else if (data.type === 'trackPageDuration')
|
||||
{
|
||||
options.time_spent = data.time;
|
||||
|
||||
mixpanel.track('Page Duration', options);
|
||||
|
||||
}
|
||||
|
||||
else if (data.type === 'trackAsset')
|
||||
{
|
||||
const options = {
|
||||
symbol: data.symbol,
|
||||
assetType: data.assetType,
|
||||
}
|
||||
|
||||
mixpanel.track('asset', options);
|
||||
|
||||
}
|
||||
|
||||
else if (data.type === 'trackButton')
|
||||
{
|
||||
const options = {
|
||||
name: data.name,
|
||||
}
|
||||
|
||||
mixpanel.track('buttonClick', options);
|
||||
|
||||
}
|
||||
|
||||
reply.send({ message: 'success' })
|
||||
})
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/save-strategy', async (request, reply) => {
|
||||
const data = request.body;
|
||||
let output;
|
||||
|
||||
try {
|
||||
output = await pb.collection("stockscreener").update(data['strategyId'], {
|
||||
'rules': data['rules']
|
||||
})
|
||||
}
|
||||
catch(e) {
|
||||
output = {};
|
||||
}
|
||||
|
||||
reply.send({ items: output })
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,157 +0,0 @@
|
||||
|
||||
function processHoldingsList(holdings, soldTicker) {
|
||||
const stockGroups = {};
|
||||
|
||||
for (const stock of holdings) {
|
||||
if (stock.symbol in stockGroups) {
|
||||
stockGroups[stock.symbol].totalCost -= stock.boughtPrice * stock.numberOfShares;
|
||||
stockGroups[stock.symbol].totalShares -= stock.numberOfShares;
|
||||
} else {
|
||||
stockGroups[stock.symbol] = {
|
||||
totalCost: stock.boughtPrice * stock.numberOfShares,
|
||||
totalShares: stock.numberOfShares,
|
||||
name: stock.name,
|
||||
assetType: stock.assetType,
|
||||
currentPrice: stock.currentPrice,
|
||||
dailyChange: stock.dailyChange,
|
||||
sinceBoughtChange: stock.sinceBoughtChange,
|
||||
};
|
||||
}
|
||||
|
||||
if (stock.symbol === soldTicker) {
|
||||
// Only update dailyChange and sinceBoughtChange for the sold ticker
|
||||
stockGroups[stock.symbol].dailyChange = stock.dailyChange;
|
||||
stockGroups[stock.symbol].sinceBoughtChange = stock.sinceBoughtChange;
|
||||
stockGroups[stock.symbol].currentPrice = stock.currentPrice;
|
||||
}
|
||||
}
|
||||
|
||||
const updatedHoldings = [];
|
||||
|
||||
for (const symbol in stockGroups) {
|
||||
const { totalCost, totalShares, name, assetType, currentPrice, dailyChange, sinceBoughtChange } = stockGroups[symbol];
|
||||
let finalBoughtPrice;
|
||||
|
||||
if (totalShares !== 0) {
|
||||
finalBoughtPrice = totalCost / totalShares;
|
||||
} else {
|
||||
// If totalShares is 0, set finalBoughtPrice to 0
|
||||
finalBoughtPrice = 0;
|
||||
}
|
||||
|
||||
const updatedStock = {
|
||||
symbol,
|
||||
name,
|
||||
assetType,
|
||||
boughtPrice: finalBoughtPrice,
|
||||
currentPrice,
|
||||
dailyChange,
|
||||
sinceBoughtChange: Number(((currentPrice / finalBoughtPrice - 1) * 100)?.toFixed(2)),
|
||||
numberOfShares: totalShares,
|
||||
};
|
||||
updatedHoldings.push(updatedStock);
|
||||
}
|
||||
|
||||
return updatedHoldings;
|
||||
}
|
||||
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
fastify.post('/sell-stock', async (request, reply) => {
|
||||
|
||||
const holidays = ['2024-01-01', '2024-01-15','2024-02-19','2024-03-29','2024-05-27','2024-06-19','2024-07-04','2024-09-02','2024-11-28','2024-12-25'];
|
||||
const currentDate = new Date().toISOString().split('T')[0];
|
||||
// Get the current time in the ET time zone
|
||||
const etTimeZone = 'America/New_York';
|
||||
const currentTime = new Date().toLocaleString('en-US', { timeZone: etTimeZone });
|
||||
|
||||
// Determine if the NYSE is currently open or closed
|
||||
const currentHour = new Date(currentTime).getHours();
|
||||
const isWeekend = new Date(currentTime).getDay() === 6 || new Date(currentTime).getDay() === 0;
|
||||
const isBeforeMarketOpen = currentHour < 9 || (currentHour === 9 && new Date(currentTime).getMinutes() < 30);
|
||||
const isAfterMarketClose = currentHour >= 16;
|
||||
|
||||
const isStockMarketOpen = !(isWeekend || isBeforeMarketOpen || isAfterMarketClose || holidays?.includes(currentDate));
|
||||
let output;
|
||||
|
||||
if (isStockMarketOpen === true) {
|
||||
|
||||
const data = request.body;
|
||||
|
||||
const currentDate = new Date();
|
||||
const year = currentDate.getFullYear();
|
||||
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is zero-based
|
||||
const day = '01';
|
||||
|
||||
const formattedDate = `${year}-${month}-${day}`; // Output: "yyyy-mm-01"
|
||||
|
||||
|
||||
|
||||
const { userId, symbol, name, numberOfShares, soldPrice } = data;
|
||||
|
||||
let currentPortfolio = await pb.collection("portfolios").getList(1, 500, {
|
||||
filter: `user="${userId}" && created >="${formattedDate}" `,
|
||||
});
|
||||
|
||||
currentPortfolio = currentPortfolio?.items[0];
|
||||
|
||||
let holdings = currentPortfolio?.holdings || [];
|
||||
let tradingHistory = currentPortfolio?.tradingHistory || [];
|
||||
let availableCash = currentPortfolio?.availableCash || 0;
|
||||
|
||||
// Find the stock in the holdings list
|
||||
const stockIndex = holdings.findIndex((stock) => stock.symbol === symbol);
|
||||
|
||||
if(stockIndex !== -1)
|
||||
{
|
||||
const soldValue = numberOfShares * soldPrice;
|
||||
// Reduce the number of shares from the existing holding
|
||||
holdings[stockIndex].numberOfShares -= numberOfShares;
|
||||
|
||||
if (holdings[stockIndex].numberOfShares <= 0) {
|
||||
// If all shares are sold, remove the stock from the holdings list
|
||||
holdings.splice(stockIndex, 1);
|
||||
}
|
||||
|
||||
// Add the sold value to the available cash
|
||||
availableCash += soldValue;
|
||||
|
||||
// Recalculate the updated holdings list
|
||||
const updatedHoldings = processHoldingsList(holdings);
|
||||
|
||||
tradingHistory.push({'symbol': symbol,
|
||||
'name': name,
|
||||
'assetType': data['assetType'],
|
||||
'numberOfShares': numberOfShares,
|
||||
'price': Number(soldPrice),
|
||||
'type': 'sell',
|
||||
'date': new Date()});
|
||||
|
||||
try {
|
||||
|
||||
await pb.collection("portfolios").update(currentPortfolio?.id, {
|
||||
"holdings": updatedHoldings,
|
||||
"availableCash": availableCash,
|
||||
"tradingHistory": tradingHistory,
|
||||
})
|
||||
output = 'success';
|
||||
|
||||
} catch (err) {
|
||||
output = 'failure';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
output = 'marketClosed'
|
||||
}
|
||||
|
||||
reply.send({ message: output })
|
||||
})
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
@ -1,141 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/upvote-comment', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
const commentId = data?.commentId;
|
||||
const postId = data?.postId;
|
||||
const userId = data?.userId;
|
||||
console.log(data)
|
||||
let output = 'failure';
|
||||
|
||||
try {
|
||||
|
||||
|
||||
let doesUserExist = await pb.collection("alreadyVoted").getList(1, 50, {
|
||||
filter: `user="${userId}"` && `comment="${commentId}"`,
|
||||
})
|
||||
|
||||
doesUserExist = doesUserExist?.items?.find(item => item?.user === userId && item?.comment === commentId);
|
||||
|
||||
const votedId = doesUserExist?.id;
|
||||
let currentVote = doesUserExist?.type;
|
||||
|
||||
//console.log('currentVote: ', currentVote)
|
||||
|
||||
|
||||
const opPost = await pb.collection('comments').getOne(commentId)
|
||||
|
||||
|
||||
//If user has no history with this post create it
|
||||
if( !currentVote || votedId === 'undefined')
|
||||
{
|
||||
|
||||
let formDataAlreadyVoted = new FormData();
|
||||
formDataAlreadyVoted.append('comment', commentId);
|
||||
formDataAlreadyVoted.append('user', userId);
|
||||
formDataAlreadyVoted.append('type', 'upvote');
|
||||
await pb.collection('alreadyVoted').create(formDataAlreadyVoted);
|
||||
|
||||
//create new record for notifications collections
|
||||
if (userId !== opPost.user)
|
||||
{
|
||||
let formDataNotifications = new FormData();
|
||||
formDataNotifications.append('opUser', opPost.user);
|
||||
formDataNotifications.append('user', userId)
|
||||
formDataNotifications.append('comment', commentId);
|
||||
formDataNotifications.append('post', postId);
|
||||
formDataNotifications.append('notifyType', 'vote');
|
||||
|
||||
await pb.collection('notifications').create(formDataNotifications);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (currentVote === 'downvote')
|
||||
{
|
||||
console.log('downvote')
|
||||
await pb.collection("comments").update(commentId, {
|
||||
"upvote+": 1,
|
||||
});
|
||||
|
||||
await pb.collection("comments").update(commentId, {
|
||||
"downvote-": 1,
|
||||
});
|
||||
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'upvote',
|
||||
});
|
||||
|
||||
//Reward: Find user of post and add +1 karma points
|
||||
let opPost = await pb.collection('comments').getOne(commentId)
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma+": 2,
|
||||
})
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if (currentVote === 'neutral' || !currentVote)
|
||||
{
|
||||
|
||||
//Reward: User of post gets +1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma+": 1,
|
||||
})
|
||||
|
||||
await pb.collection("comments").update(commentId, {
|
||||
"upvote+": 1,
|
||||
});
|
||||
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'upvote',
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
await pb.collection("comments").update(commentId, {
|
||||
"upvote-": 1,
|
||||
});
|
||||
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'neutral',
|
||||
});
|
||||
|
||||
//Reset Reward: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 1,
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch(e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
|
||||
reply.send({ items: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
@ -1,137 +0,0 @@
|
||||
// Declare a route
|
||||
module.exports = function (fastify, opts, done) {
|
||||
|
||||
const pb = opts.pb;
|
||||
|
||||
fastify.post('/upvote', async (request, reply) => {
|
||||
const data = request.body;
|
||||
|
||||
const postId = data?.postId;
|
||||
const userId = data?.userId;
|
||||
|
||||
let output = 'failure';
|
||||
|
||||
|
||||
try {
|
||||
|
||||
|
||||
let doesUserExist = await pb.collection("alreadyVoted").getList(1, 50, {
|
||||
filter: `user="${userId}"` && `post="${postId}"`,
|
||||
})
|
||||
|
||||
doesUserExist = doesUserExist?.items?.find(item => item?.user === userId && item?.post === postId);
|
||||
|
||||
const votedId = doesUserExist?.id;
|
||||
let currentVote = doesUserExist?.type;
|
||||
|
||||
//console.log('currentVote: ', currentVote)
|
||||
|
||||
|
||||
const opPost = await pb.collection('posts').getOne(postId)
|
||||
|
||||
//If user has no history with this post create it
|
||||
if( !currentVote || votedId === 'undefined')
|
||||
{
|
||||
|
||||
let formDataAlreadyVoted = new FormData();
|
||||
formDataAlreadyVoted.append('post', postId);
|
||||
formDataAlreadyVoted.append('user', userId);
|
||||
formDataAlreadyVoted.append('type', 'upvote');
|
||||
await pb.collection('alreadyVoted').create(formDataAlreadyVoted);
|
||||
|
||||
//create new record for notifications collections
|
||||
if (userId !== opPost.user)
|
||||
{
|
||||
let formDataNotifications = new FormData();
|
||||
formDataNotifications.append('opUser', opPost.user);
|
||||
formDataNotifications.append('user', userId)
|
||||
formDataNotifications.append('post', postId);
|
||||
formDataNotifications.append('notifyType', 'vote');
|
||||
|
||||
await pb.collection('notifications').create(formDataNotifications);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (currentVote === 'downvote')
|
||||
{
|
||||
console.log('downvote')
|
||||
await pb.collection("posts").update(postId, {
|
||||
"upvote+": 1,
|
||||
});
|
||||
|
||||
await pb.collection("posts").update(postId, {
|
||||
"downvote-": 1,
|
||||
});
|
||||
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'upvote',
|
||||
});
|
||||
|
||||
//Reward: Find user of post and add +1 karma points
|
||||
let opPost = await pb.collection('posts').getOne(postId)
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma+": 2,
|
||||
})
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if (currentVote === 'neutral' || !currentVote)
|
||||
{
|
||||
|
||||
//Reward: User of post gets +1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma+": 1,
|
||||
})
|
||||
|
||||
await pb.collection("posts").update(postId, {
|
||||
"upvote+": 1,
|
||||
});
|
||||
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'upvote',
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
await pb.collection("posts").update(postId, {
|
||||
"upvote-": 1,
|
||||
});
|
||||
|
||||
|
||||
await pb.collection("alreadyVoted").update(votedId, {
|
||||
"type": 'neutral',
|
||||
});
|
||||
|
||||
//Reset Reward: Find user of post and subtract -1 karma points
|
||||
await pb.collection("users").update(opPost.user, {
|
||||
"karma-": 1,
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
catch(e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
|
||||
reply.send({ items: output })
|
||||
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user