rss-parser reposts same every time - javascript

I wanted some help on the rss-parser, So I wanted to make the command send the message to the channel only once, but at a certain time it keeps Re reposting the same thing every time and I am not able to resolve this.
(async function main() {
// Make a new RSS Parser
const parser = new Parser();
// Get all the items in the RSS feed
const feed = await parser.parseURL("https://imaginescan.com.br/feed"); // https://www.reddit.com/.rss
let items = [];
// Clean up the string and replace reserved characters
const fileName = `${feed.title.replace(/\s+/g, "-").replace(/[/\\?%*:|"<>]/g, '').toLowerCase()}.json`;
if (fs.existsSync(fileName)) {
items = require(`./${fileName}`);
}
// Add the items to the items array
await Promise.all(feed.items.map(async (currentItem) => {
// Add a new item if it doesn't already exist
if (items.filter((item) => isEquivalent(item, currentItem)).length <= 0) {
items.push(currentItem);
}
}));
// Save the file
fs.writeFileSync(fileName, JSON.stringify(items));
feed.items.reverse().forEach(async (item) => {
const channel = client.channels.cache.get('980990991865626634');
let embed = new Discord.MessageEmbed()
.setTitle("New Cap")
.setDescription(item.title)
.setColor("PURPLE")
.setImage()
channel.send(embed)
})
})();
function isEquivalent(a, b) {
// Create arrays of property names
let aProps = Object.getOwnPropertyNames(a);
let bProps = Object.getOwnPropertyNames(b);
// if number of properties is different, objects are not equivalent
if (aProps.length != bProps.length) {
return false;
}
for (let i = 0; i < aProps.length; i++) {
let propName = aProps[i];
// if values of same property are not equal, objects are not equivalent
if (a[propName] !== b[propName]) {
return false;
}
}
// if we made it this far, objects are considered equivalent
return true;
}
I'm new to this, so I wanted some help with this problem.

Related

iterating Javascript array and delete based on condition

I want to iterate through an array of words, look up the definition and delete the word if no definition is found.
my code looks as follows;
var words = ["word1", "word2", "word3",]
function Meaning(words){
const getMeaning = async () => {
const response = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${words}`)
const myJson = await response.json()
for(i = 0; i < words.length; ++i) {
if(!response[i]){
myJson.splice(i,1)
console.log(myJson)
}
}}
This is not really doing anything atm. Where am I going wrong?
edit to add context
tried like this as well;
for(i = 0; i < words.length; ++i)
fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${words[i]}`).then((response) => {
if (response === 404) {
let response = words
words[i].splice(i,1)
console.log(response)
}
throw new Error('Something went wrong');
})
.then((responseJson) => {
let response = words
response[i].splice(i,1)
})
.catch((error) => {
console.log(error)
});
I can print out the 404 error when it finds no definition, but I can't remove it from the words array
After quick look at the API, and it appears to handle only single words, so the caller needs to make the requests one at a time. Here's how to do it...
const baseUrl = 'https://api.dictionaryapi.dev/api/v2/entries/en/';
// one word lookup. resolve to an array of definitions
async function lookupWord(word) {
const res = await fetch(baseUrl + word);
return res.json();
}
// resolve to a bool, true if the word is in the corpus
async function spellCheck(word) {
const defArray = await lookupWord(word);
return Array.isArray(defArray) && defArray.length > 0;
}
// create a spellCheck promise for every word and resolve with the results
// note, this mutates the array and resolves to undefined
async function spellCheckWords(array) {
const checks = await Promise.all(array.map(spellCheck));
for (let i=array.length-1; i>=0; i--) {
if (!checks[i]) array.splice(i,1);
}
}
// test it (a little)
let array = ['hello', 'whereforeartthou', 'coffee'];
spellCheckWords(array).then(() => {
console.log(array)
})
try this code, you need to check every single element of array from response
var words = ["word1", "word2", "word3"];
function Meaning(words) {
const getMeaning = async () => {
const response = await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${words}`)
const myJson = await response.json()
let result = [];
myJson.forEach(element => {
if(words.includes(element)) {
result.push(element)
}
});
return result;
}
return getMeaning();
}

Cannot push JSON elements to array inside for loop called from useEffect

I have an array candleRealTimeDataQueue which is not getting updated properly. Please find the code below:
let candleCurrentJSONDataWS = null;
var candleRealTimeDataQueue = [];
let tempDateTime = null;
let candleJsonData = {};
useEffect(() => {
getDataFromAPI();
}, []);
...
const getDataFromAPI = async () => {
let apiDataFetch = await fetch('https:/api/endpoint');
let response = await apiDataFetch.json(); // data from api obtained correctly
// total 4 values
for (var i = 0; i < 4; i++) {
tempDateTime = new Date(parseInt(response[i][0]));
candleJsonData['time'] = tempDateTime.toString();
candleJsonData['open'] = parseFloat(response[i][1]);
candleJsonData['high'] = parseFloat(response[i][2]);
candleJsonData['low'] = parseFloat(response[i][3]);
candleJsonData['close'] = parseFloat(response[i][4]);
console.log(candleJsonData); // this correctly prints different
// data for each different i
candleRealTimeDataQueue.push(candleJsonData);
console.log(candleRealTimeDataQueue); // PROBLEM is here: At the end
// candleRealTimeDataQueue array all
// have SAME elements. Its wrong. All
// 4 elements are of i = 3
}
}
Problem is at the end candleRealTimeDataQueue has 4 elements and all the elements are same. This should not happen because I am pushing DIFFERENT candleJsonData elements in the candleRealTimeDataQueue array in the for loop. Please help.
I believe the problem here is that you are reusing the candleJsonData object. When you run candleRealTimeDataQueue.push(candleJsonData), you are pushing the reference to candleJsonData into candleRealTimeDataQueue. So at the end of the loop, you have four references to the same object inside candleRealTimeDataQueue. And since you are modifying the same candleJsonData object over and over again, you'll just see four identical json data inside the queue when you log it and all four elements will be of i = 3.
Instead, you should be creating new candleJsonData objects inside your loop. So something like
for (var i = 0; i < 4; i++) {
tempDateTime = new Date(parseInt(response[i][0]));
let candleJsonData = {}
candleJsonData['time'] = tempDateTime.toString();
candleJsonData['open'] = parseFloat(response[i][1]);
candleJsonData['high'] = parseFloat(response[i][2]);
candleJsonData['low'] = parseFloat(response[i][3]);
candleJsonData['close'] = parseFloat(response[i][4]);
candleRealTimeDataQueue.push(candleJsonData);
}
it is because of the candleJsonData variable which is declared outside, so latest value is overriding previous value. In face there is no need of that variable and it can directly push in the array.
var candleRealTimeDataQueue = [];
React.useEffect(() => {
getDataFromAPI().then((data) => {
for (let i = 0; i < 4; i++) {
candleRealTimeDataQueue.push({
time: new Date(parseInt(data[i][0])).toString(),
open: parseFloat(data[i][1]),
low: parseFloat(data[i][3]),
close: parseFloat(data[i][4]),
});
}
});
return () => {
// do clean up here
};
}, []);
const getDataFromAPI = () => {
return fetch('https:/api/endpoint');
};

Why is my for loop not working how I expect to? Run function twice - JavaScript

So guys, I've got scraping function, where I create object of scraped data. Code of scraper is:
const axios = require('axios');
const cheerio = require('cheerio');
const db = require('../config/db.config');
const Article = db.article;
const prices = new Array();
const ids = new Array();
const descs = new Array();
const links = new Array();
for (p = 1; p < 3; p++) {
function again() {
const url = `https://www.olx.ba/pretraga?vrsta=samoprodaja&kategorija=23&sort_order=desc&kanton=9&sacijenom=sacijenom&stranica=${p}`;
axios
.get(url)
.then((response) => {
let $ = cheerio.load(response.data);
$('div[class="naslov"] > a').each((i, el) => {
const id = $(el).attr('href'); // ID, description and link are in the same div class
const desc = id;
const link = id;
descs.push(desc.substring(36)); //Retriving description with substring and push into array
ids.push(id.substring(27, 35)); //Retriving id with substring and push into array
links.push(link); //Retriving link and push into array
for (var i = 0; i < descs.length; i++) {
descs[i] = descs[i].replace('/', '').replace('-', ' ');
}
});
$('div[class="datum"] > span').each((i, el) => {
$('span[class="prekrizenacijena"]').remove();
const price = $(el).text();
prices.push(price); //Retriving price and push into array
});
for (var i = prices.length - 1; i >= 0; i--) {
if (prices[i] === 'PO DOGOVORU') {
prices.splice(i, 1);
}
}
async function asy() {
const sqm = new Array();
for (k = 0; k < links.length; k++) {
const res = await axios
.get(`${links[k]}`)
.then((result) => {
let $ = cheerio.load(result.data);
const pr = $('div[class="df2 "]').first().text();
sqm.push(pr);
for (var i = 0; i < sqm.length; i++) {
sqm[i] = sqm[i].replace('m2', '');
}
})
.catch((err) => {
//handle error
console.log(err);
});
}
const object = ids.map((element, index) => {
const ppm2 =
parseFloat(
prices[index].replace(/\.| ?€$/g, '').replace(',', '.')
) / parseFloat(sqm[index]);
const ppm2final = Math.round(ppm2);
return {
id: element,
price: prices[index],
descr: descs[index],
link: links[index],
sqm: sqm[index],
ppm2: ppm2final + ' KM',
};
});
console.log(object);
console.log(Object.keys(object).length);
/*const ins = await Article.bulkCreate(object)
.then(console.log('Data added to DB'))
.catch((err) => console.log(err));*/
}
asy();
})
.catch((e) => {
console.log(e);
});
}
again();
}
Now when I delete first for lop and function again() and instead of ${p} in url insert eg. 1,2,3 etc. it's working perfect - sqm is fetched for correct link.
Now the problem:
I want to run this url multiple times because ${p} is number of page on that url. Now first problem I got:
sqm isn't correct - sqm data is thrown all over the object and isn't correct for that link.(it's correct when I don't use ${p}
First time i get sqm data(but not correct for that link), when function needs to get ran second time (for second page - to ${p}=2) - sqm isn't fetched at all (it throws NaN).
Also I've got console.log(Object.keys(object).length); where I expect first time to be 30, then after is runned second time to I get 60.(each page contains 30 articles), but I get 60, then again 60.
I've tried with many things: async functions, putting axios to await etc. but nothing really work - sometimes I get only 30 articles, sometimes 60 but with incorrect values.

Converting Tree Like File Directory to a JSON object

I'm trying to convert a file directory response into a JSON object.
Here's a copy of the response from the file directory function.
[ 'C:/Users/Freddy/System/storage/Objects/Users/1',
'C:/Users/Freddy/System/storage/Objects/Users/1/email',
'C:/Users/Freddy/System/storage/Objects/Users/1/email/FreddyMcGee#Gmail.com',
'C:/Users/Freddy/System/storage/Objects/Users/1/etc',
'C:/Users/Freddy/System/storage/Objects/Users/1/etc/etc',
'C:/Users/Freddy/System/storage/Objects/Users/1/password',
'C:/Users/Freddy/System/storage/Objects/Users/1/password/123123123213',
'C:/Users/Freddy/System/storage/Objects/Users/1/username',
'C:/Users/Freddy/System/storage/Objects/Users/1/username/Freddy1337' ]
And this is the ouput that i'm trying/aiming to achieve:
1 : {
email: "FreddyMcGee#Gmail.com",
etc: etc,
password: "12313123",
username: "Freddy1337"
}
Simply the shortest path in the directory is the start of JSON object. All previous 'folder directories' are clipped.
I've attempted myself to write a function that does so, however I had some trouble since the folder 'Users' appears twice. Also the function doesn't traverse the nodes properly, it just cuts it at set sections and glues them together. It's very horrible, i'm a bit ashamed.
function TreeToJson(directory, cutAfter){
for (var i = directory.length - 1; i >= 0; i--) {
directory[i] = directory[i].substr(directory[i].indexOf(cutAfter) + cutAfter.length, directory[i].length - 1);
directory[i] = directory[i].split("/");
directory[i].shift();
};
jsonA = {}; jsonB = {}; jsonC = {};
for (var i = 0; i < directory.length; i++) {
if(directory[i][2] != undefined){
jsonB[directory[i][2]] = directory[i][3]
}
};
jsonC[Number([directory[0][1]])] = jsonB;
jsonA[directory[0][0]] = jsonC;
return jsonA;
}
TreeToJson(files, 'Objects');
If someone can show me a better approach into converting a 'Tree View Model' into a 'JSON Object' i'd appreciate it. I'm curious on the approaches other developers would take, and also what the most simplest solution would be.
A very common operation is extracting the part of the string after the last slash, so I'd make a regular expression function for that. Identify the starting directory name from the first element in the array, and then use a simple for loop to iterate through the rest of the array, two-by-two, extracting the keys and values:
const input = [
'C:/Users/Freddy/System/storage/Objects/Users/1',
'C:/Users/Freddy/System/storage/Objects/Users/1/email',
'C:/Users/Freddy/System/storage/Objects/Users/1/email/FreddyMcGee#Gmail.com',
'C:/Users/Freddy/System/storage/Objects/Users/1/etc',
'C:/Users/Freddy/System/storage/Objects/Users/1/etc/etc',
'C:/Users/Freddy/System/storage/Objects/Users/1/password',
'C:/Users/Freddy/System/storage/Objects/Users/1/password/123123123213',
'C:/Users/Freddy/System/storage/Objects/Users/1/username',
'C:/Users/Freddy/System/storage/Objects/Users/1/username/Freddy1337'
];
const lastPart = str => str.match(/\/([^\/]+)$/)[1];
const [baseDirectory, ...keysVals] = input;
const dirName = lastPart(baseDirectory);
const dirObj = {};
for (let i = 0; i < keysVals.length; i += 2) {
const key = lastPart(keysVals[i]);
const val = lastPart(keysVals[i + 1]);
dirObj[key] = val;
}
const output = { [dirName]: dirObj };
console.log(output);
you can split by 'Users' and .reduce() the resulting array :
const data = ['C:/Users/Freddy/System/storage/Objects/Users/1',
'C:/Users/Freddy/System/storage/Objects/Users/1/email',
'C:/Users/Freddy/System/storage/Objects/Users/1/email/FreddyMcGee#Gmail.com',
'C:/Users/Freddy/System/storage/Objects/Users/1/etc',
'C:/Users/Freddy/System/storage/Objects/Users/1/etc/etc',
'C:/Users/Freddy/System/storage/Objects/Users/1/password',
'C:/Users/Freddy/System/storage/Objects/Users/1/password/123123123213',
'C:/Users/Freddy/System/storage/Objects/Users/1/username',
'C:/Users/Freddy/System/storage/Objects/Users/1/username/Freddy1337'
];
const objects = data
.map(e => {
return e.split('Users')[2];
})
.reduce((all, curr) => {
let elems = curr.split('/');
all[elems[1]] = all[elems[1]] || {};
if ([elems[2]] && elems[3]) {
Object.assign(all[elems[1]], {
[elems[2]]: elems[3]
})
}
// elems[1] is : 1
// elems[2] is the key ( username, password .. )
// elems[3] is the value ( Freddy1337 ... )
return all;
}, {})
console.log(objects)
EDIT : same code above wrapped in a function :
const tree = ['C:/Users/Freddy/System/storage/Objects/Users/1',
'C:/Users/Freddy/System/storage/Objects/Users/1/email',
'C:/Users/Freddy/System/storage/Objects/Users/1/email/FreddyMcGee#Gmail.com',
'C:/Users/Freddy/System/storage/Objects/Users/1/etc',
'C:/Users/Freddy/System/storage/Objects/Users/1/etc/etc',
'C:/Users/Freddy/System/storage/Objects/Users/1/password',
'C:/Users/Freddy/System/storage/Objects/Users/1/password/123123123213',
'C:/Users/Freddy/System/storage/Objects/Users/1/username',
'C:/Users/Freddy/System/storage/Objects/Users/1/username/Freddy1337'
];
function TreeToJson(data, cutAfter){
const objects = data
.map(e => {
return e.split(cutAfter)[1];
})
.reduce((all, curr) => {
let elems = curr.split('/');
all[elems[2]] = all[elems[2]] || {};
if([elems[3]] && elems[4]){
Object.assign(all[elems[2]], {
[elems[3]] : elems[4]
})
}
return all;
}, {})
return objects;
}
console.log(TreeToJson(tree, 'Objects'))

I am trying to find times in an array of objects using the value of my input field

I will try my best to explain this. I have an input field which allows the user to enter a certain time. I also have an array of attractions that have times with them. Once the user enters a time and clicks a button, all arrtactions with that time should load to dom. The event listener is working, but every attraction is printing, even the ones without times. Below is what I have so far. I believe I am just missing some minor details.
<input id="timeInput" type="text" placeholder="Ex: 1:00 PM">
<button id="timeBtn">Show me Scheduled Events!</button>
let timeTest = [];
let timesArray = [];
let timeSearch = document.getElementById("timeInput");
$('#timeBtn').on('click',((e) => {
timeTest.push(timeSearch.value);
let timeSplit = timeTest[1].split(":");
let hourSelected = timeSplit[0];
let morningOrEvening = timeSplit[1];
controller.getType()
.then((data) => {
for(let i = 0; i < data.length; i++) {
if (data[i].times !== undefined) {
if (timeValueCheck(data[i].times)) {
timesArray.push(data[i]);
}
else {
timesArray.push(data[i]);
}
}}
timesArray.forEach(attraction =>{
$('#output').append(attrHBS(attraction));
console.log(attraction);
}
);
}
);
}));
let timeValueCheck= (timesArray) => {
let timeSplit = timeTest[1].split(":");
let hourSelected = timeSplit[0];
let morningOrEvening = timeSplit[1];
for (let i=0; i < timesArray.length; i++) {
let splitArray = timesArray[i].split(":");
console.log("super", splitArray);
if (hourSelected === splitArray[0]){
console.log("mega",hourSelected, splitArray[0]);
return true;
}
}
return false;
};
// this is what is inside controller.js
module.exports.getType = (attrData) => {
//creating new Promise to load when used in other functions
return new Promise((resolve, reject) => {
//getting our data from two ajax calls, attractions and attraction types
let p1 = factory.getAttractionData();
let p2 = factory.getAttTypes();
// empty array to push data into once we have manipulated it
let newDataWithTypes = [];
//promise all to get both data types before using them.
Promise.all([p1,p2])
.then((attrData) => {
// loop over the first array, all 132 attractions
attrData[0].forEach(allAttractions => {
// loop over second array, the 8 types
attrData[1].forEach(typeofAttractions => {
// if statement to add the types to each attraction based on their type id!
if (allAttractions.type_id === typeofAttractions.id) {
allAttractions.type = typeofAttractions.name;
// pushes to the array on 32
newDataWithTypes.push(allAttractions);
}
});
});
resolve(newDataWithTypes);
}
);
});
};
Array's index in javascript begins with 0.I think this is the problem.
try this
let timeSplit = timeTest[0].split(":");...
instead of
let timeSplit = timeTest[1].split(":");...
Shouldn't this line be '0':
let timeSplit = timeTest[0].split(":")

Categories

Resources