DDG, cats, refactor and more
This commit is contained in:
@@ -11,7 +11,7 @@ Link Flayer is a Discord Bot designed to provide your Discord server with RSS Ne
|
|||||||
- Setup has been moved from config file to environment variables to assume bot runs from one instance
|
- Setup has been moved from config file to environment variables to assume bot runs from one instance
|
||||||
|
|
||||||
## Configure your feeds.json:
|
## Configure your feeds.json:
|
||||||
Each node with a "title", "link", category attribute to be used from an Airtable.
|
Each node with a "title", "link", "category" attribute to be used from an Airtable columns.
|
||||||
Setting up Airtable for multiple Discord severs still in progress.
|
Setting up Airtable for multiple Discord severs still in progress.
|
||||||
It should be assumed every server will need its own Airtable Base and the coresponding apiKey, base and table name.
|
It should be assumed every server will need its own Airtable Base and the coresponding apiKey, base and table name.
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ var libFlayer = require("../libFlayer.js");
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'categories',
|
name: 'categories',
|
||||||
description: 'Categories',
|
description: 'Categories',
|
||||||
async execute(message) {
|
execute(message) {
|
||||||
|
var cats = libFlayer.getCategories();
|
||||||
|
|
||||||
message.reply(
|
message.reply(
|
||||||
`Categories: [General, Entertainment, Sports, Tech]`
|
`Categories: [${cats.join(', ')}]`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
17
index.js
17
index.js
@@ -11,8 +11,11 @@ const express = require("express");
|
|||||||
const server = express();
|
const server = express();
|
||||||
var libFlayer = require("./libFlayer.js");
|
var libFlayer = require("./libFlayer.js");
|
||||||
|
|
||||||
|
|
||||||
|
let linkFlayerMap = [];
|
||||||
|
|
||||||
server.all("/",(req, res) => {
|
server.all("/",(req, res) => {
|
||||||
var htmlOutput = "Bot is Ready - Sources loading <br />";
|
var htmlOutput = "LinkFlayer Bot is Ready - Sources loading <br />";
|
||||||
|
|
||||||
var sources = libFlayer.getSources();
|
var sources = libFlayer.getSources();
|
||||||
sources.forEach(source => {
|
sources.forEach(source => {
|
||||||
@@ -21,8 +24,15 @@ server.all("/",(req, res) => {
|
|||||||
|
|
||||||
<div> Title: ${source.title} </div>
|
<div> Title: ${source.title} </div>
|
||||||
<div> Link: ${source.link} </div>
|
<div> Link: ${source.link} </div>
|
||||||
|
<div> category: ${source.category} </div>
|
||||||
|
|
||||||
</div>`
|
</div>
|
||||||
|
<div>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
`
|
||||||
});
|
});
|
||||||
res.send(htmlOutput);
|
res.send(htmlOutput);
|
||||||
|
|
||||||
@@ -45,9 +55,6 @@ for (const file of commandFiles) {
|
|||||||
client.commands.set(command.name, command);
|
client.commands.set(command.name, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let linkFlayerMap = [];
|
|
||||||
|
|
||||||
client.on('ready', () => {
|
client.on('ready', () => {
|
||||||
console.log(`Logged in as ${client.user.tag}!`);
|
console.log(`Logged in as ${client.user.tag}!`);
|
||||||
});
|
});
|
||||||
|
|||||||
244
libFlayer.js
244
libFlayer.js
@@ -1,75 +1,93 @@
|
|||||||
|
// JD Requires
|
||||||
let Parser = require('rss-parser');
|
let Parser = require('rss-parser');
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
let parser = new Parser();
|
let parser = new Parser();
|
||||||
|
|
||||||
var feeds = [];
|
|
||||||
var jsonfile = require('jsonfile');
|
var jsonfile = require('jsonfile');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var file = ('./feeds.json');
|
var file = ('./feeds.json');
|
||||||
var Airtable = require('airtable');
|
var Airtable = require('airtable');
|
||||||
|
|
||||||
var apiKey=process.env.KEY;
|
// Data Structures
|
||||||
var userBase=process.env.BASE;
|
var feeds = [];
|
||||||
var userTable =process.env.TABLE
|
let linkFlayerMap = [];
|
||||||
|
let linkFlayerCats = [];
|
||||||
|
|
||||||
|
//Aitrable Setup
|
||||||
|
var apiKey = process.env.KEY;
|
||||||
|
var userBase = process.env.BASE;
|
||||||
|
var userTable = process.env.TABLE
|
||||||
|
|
||||||
token = process.env.TOKEN;
|
token = process.env.TOKEN;
|
||||||
var base = new Airtable({apiKey: apiKey}).base(userBase);
|
var base = new Airtable({
|
||||||
|
apiKey: apiKey
|
||||||
|
}).base(userBase);
|
||||||
|
|
||||||
let linkFlayerMap = [];
|
//DuckDuckGo related structure
|
||||||
let answerData = {
|
let answerData = {
|
||||||
text: ``,
|
text: ``,
|
||||||
source: ``
|
source: ``
|
||||||
}
|
}
|
||||||
|
|
||||||
const { quotes } = require('./quotes.json');
|
//Local DB for quotes
|
||||||
|
const {
|
||||||
|
quotes
|
||||||
|
} = require('./quotes.json');
|
||||||
|
|
||||||
exports.addSource = function(title,link,category){
|
/**
|
||||||
|
* Adds a new source url to configured Airtable
|
||||||
|
* @constructor
|
||||||
|
* @param {string} title - Title/Name of the RSS feed.
|
||||||
|
* @param {string} link - URL of RSS feed.
|
||||||
|
* @param {string} category - Category of RSS feed.
|
||||||
|
*/
|
||||||
|
exports.addSource = function (title, link, category) {
|
||||||
|
|
||||||
for (i=0; i<feeds.length; i++){
|
for (i = 0; i < feeds.length; i++) {
|
||||||
if (feeds[i].link == link){
|
if (feeds[i].link == link) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
base(userTable).create([
|
base(userTable).create([{
|
||||||
{
|
"fields": {
|
||||||
"fields": {
|
"title": title,
|
||||||
"title": title,
|
"link": link,
|
||||||
"link": link,
|
"category": category
|
||||||
"category": category
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
], function(err, record) {
|
}], function (err, record) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(record.getId());
|
console.log(record.getId());
|
||||||
|
|
||||||
var linkData = {
|
var linkData = {
|
||||||
title: `${title}`,
|
title: `${title}`,
|
||||||
link: `${link}`,
|
link: `${link}`,
|
||||||
category: `${category}`,
|
category: `${category}`,
|
||||||
id: record.getId()
|
id: record.getId()
|
||||||
}
|
}
|
||||||
|
|
||||||
feeds.push(linkData);
|
feeds.push(linkData);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.deleteSource = function(title) {
|
/**
|
||||||
|
* Deletes a new source url to configured Airtable by title
|
||||||
|
* @constructor
|
||||||
|
* @param {string} title - Title/Name of the RSS feed.
|
||||||
|
*/
|
||||||
|
exports.deleteSource = function (title) {
|
||||||
var deleteRecord = "";
|
var deleteRecord = "";
|
||||||
for (i=0; i<feeds.length; i++){
|
for (i = 0; i < feeds.length; i++) {
|
||||||
if (feeds[i].title == title){
|
if (feeds[i].title == title) {
|
||||||
deleteRecord = feeds[i].id;
|
deleteRecord = feeds[i].id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base(userTable).destroy(deleteRecord, function(err, deletedRecord) {
|
base(userTable).destroy(deleteRecord, function (err, deletedRecord) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return;
|
return;
|
||||||
@@ -78,95 +96,108 @@ exports.deleteSource = function(title) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
exports.sleep = (ms) => new Promise((resolve) => { setTimeout(resolve, ms); })
|
* Adds a new source url to configured Airtable
|
||||||
|
* @constructor
|
||||||
|
* @param {string} feedType - Category to select Feed by.
|
||||||
|
*/
|
||||||
exports.getFeeds = function (feedType) {
|
exports.getFeeds = function (feedType) {
|
||||||
var linkFlayerFilteredMap = [];
|
var linkFlayerFilteredMap = [];
|
||||||
if (feedType == null || feedType == undefined || feedType == "") {
|
if (feedType == null || feedType == undefined || feedType == "") {
|
||||||
return linkFlayerMap;
|
return linkFlayerMap;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
linkFlayerMap.forEach(linkFlay => {
|
linkFlayerMap.forEach(linkFlay => {
|
||||||
if (linkFlay.category.toLowerCase().indexOf(feedType.toLowerCase()) > -1) {
|
if (linkFlay.category.toLowerCase().indexOf(feedType.toLowerCase()) > -1) {
|
||||||
linkFlayerFilteredMap.push(linkFlay);
|
linkFlayerFilteredMap.push(linkFlay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return linkFlayerFilteredMap;
|
return linkFlayerFilteredMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getSources = function () {
|
exports.loadFeeds = function () {
|
||||||
return feeds;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getQuotes = function () {
|
|
||||||
return quotes;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.loadFeeds = function() {
|
|
||||||
feeds = [];
|
feeds = [];
|
||||||
|
linkFlayerMap = [];
|
||||||
|
linkFlayerCats = [];
|
||||||
|
|
||||||
base(userTable)
|
base(userTable)
|
||||||
.select().eachPage(function page(records, fetchNextPage) {
|
.select().eachPage(function page(records, fetchNextPage) {
|
||||||
try {
|
try {
|
||||||
records.forEach(function(record) {
|
records.forEach(function (record) {
|
||||||
console.log('Retrieved title: ', record.get('title'));
|
console.log('Retrieved title: ', record.get('title'));
|
||||||
console.log('Retrieved link:', record.get('link'));
|
console.log('Retrieved link:', record.get('link'));
|
||||||
console.log('Retrieved category:', record.get('category'));
|
console.log('Retrieved category:', record.get('category'));
|
||||||
|
|
||||||
var feedData = {
|
var feedData = {
|
||||||
title: `${unescape(record.get('title'))}`,
|
title: `${unescape(record.get('title'))}`,
|
||||||
link: `${unescape(record.get('link'))}`,
|
link: `${unescape(record.get('link'))}`,
|
||||||
category: `${unescape(record.get('category'))}`,
|
category: `${unescape(record.get('category'))}`,
|
||||||
id: record.getId()
|
id: record.getId()
|
||||||
}
|
|
||||||
|
|
||||||
feeds.push(feedData);
|
|
||||||
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
linkFlayerMap = [];
|
feeds.push(feedData);
|
||||||
feeds.forEach(feedBlock => {
|
|
||||||
|
let foundCat = false;
|
||||||
|
linkFlayerCats.forEach(cat => {
|
||||||
|
if (cat == record.get('category')) {
|
||||||
|
foundCat = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!foundCat) {
|
||||||
|
linkFlayerCats.push(record.get('category'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
feeds.forEach(feedBlock => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const feed = parser.parseURL(feedBlock.link, function(err, feed) {
|
const feed = parser.parseURL(feedBlock.link, function (err, feed) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(err + " " + feedBlock.link);
|
console.log(err + " " + feedBlock.link);
|
||||||
//return;
|
//return;
|
||||||
}
|
}
|
||||||
console.log(feed.title);
|
console.log(feed.title);
|
||||||
feed.items.forEach(item => {
|
feed.items.forEach(item => {
|
||||||
|
|
||||||
var linkData = {
|
var linkData = {
|
||||||
title: `${unescape(item.title)}`,
|
title: `${unescape(item.title)}`,
|
||||||
link: `${unescape(item.link)}`,
|
link: `${unescape(item.link)}`,
|
||||||
category: `${unescape(feedBlock.category)}`
|
category: `${unescape(feedBlock.category)}`
|
||||||
}
|
}
|
||||||
linkFlayerMap.push(linkData);
|
linkFlayerMap.push(linkData);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
})().then();
|
})().then();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
//fetchNextPage();
|
||||||
|
}, function done(error) {
|
||||||
|
console.log(error);
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
//fetchNextPage();
|
|
||||||
}, function done(error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getAnswer = async function (question) {
|
exports.getAnswer = async function (question) {
|
||||||
|
|
||||||
var answerURL = `https://api.duckduckgo.com/?q=${question}&format=json&pretty=1`;
|
var answerURL = `https://api.duckduckgo.com/?q=${question}&format=json&pretty=1`;
|
||||||
console.log(answerURL);
|
console.log(answerURL);
|
||||||
await axios.get(answerURL)
|
answerData = {
|
||||||
|
text: ``,
|
||||||
|
source: ``
|
||||||
|
}
|
||||||
|
await axios.get(answerURL)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
console.log(response.data.RelatedTopics[0].Text);
|
console.log(response.data.RelatedTopics[0].Text);
|
||||||
console.log(response.data.RelatedTopics[0].FirstURL);
|
console.log(response.data.RelatedTopics[0].FirstURL);
|
||||||
@@ -182,11 +213,42 @@ exports.getAnswer = async function (question) {
|
|||||||
source: `${unescape(response.data.RelatedTopics[0].FirstURL)}`
|
source: `${unescape(response.data.RelatedTopics[0].FirstURL)}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return answerData;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
return answerData;
|
return answerData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getQuotes - Returns libFlayer feed sources
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
exports.getSources = function () {
|
||||||
|
return feeds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getQuotes - Returns libFlayer feed quotes
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
exports.getQuotes = function () {
|
||||||
|
return quotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getCategories - Returns libFlayer feed categories
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
exports.getCategories = function () {
|
||||||
|
return linkFlayerCats;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sleep - sleep/wait
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
exports.sleep = (ms) => new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, ms);
|
||||||
|
})
|
||||||
|
|||||||
1135
package-lock.json
generated
1135
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,9 @@
|
|||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
|
"js-doc": "^0.5.0",
|
||||||
"jsonfile": "^6.1.0",
|
"jsonfile": "^6.1.0",
|
||||||
|
"parse-files": "^0.1.1",
|
||||||
"rss-parser": "^3.12.0"
|
"rss-parser": "^3.12.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -23,5 +25,8 @@
|
|||||||
"local": "heroku local web"
|
"local": "heroku local web"
|
||||||
},
|
},
|
||||||
"author": "John Facey",
|
"author": "John Facey",
|
||||||
"license": "ISC"
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"jsdoc": "^3.6.7"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user