Add YTfeeds to dashboards

master
Cristiano Pires 2 years ago
parent ac8cff2202
commit 1062d22b17

@ -19,6 +19,7 @@ class setYTFeed extends Command{
const validationResult = await this.confirmArgs(message, args);
if (validationResult.error) return new ErrorMessage(this.client).send(ErrorType.Arguments, message, [validationResult.error])
var feed = new feedM();
feed.gID = message.guildId;
feed.ChannelId = validationResult.channelId
feed.YTChannelId = validationResult.YTChannelId;
feed.CostumMessage = args[3]?args.splice(2).join(' '):'New video:';
@ -132,3 +133,4 @@ async function getChannelId(url)
return data ? data.split('https://www.youtube.com/feeds/videos.xml?channel_id=')[1].split('"')[0] : false;
}
}

@ -1,5 +1,7 @@
const GuildM = require('../models/guilds');
const roleRulesM = require('../models/autoRoleRule')
const roleRulesM = require('../models/autoRoleRule');
const feedsM = require('../models/feeds')
const xmlparser = require('xml-js')
exports.getUser = (io)=>
{
@ -113,6 +115,7 @@ exports.getMessage = (bot)=>
{
return async (req, res)=>
{
if(!req.headers.guildid && !req.headers.messageid) return res.json({error:'No gid or messageid or both.'})
const TextChannels = bot.guilds.cache.get(req.headers.guildid).channels.cache.filter(x=>x.type==0);
TextChannels.forEach(channel => {
(async (channel)=>
@ -230,3 +233,138 @@ exports.updateRule = (bot)=>
return {mID, roleID, roleEmoji, roleName, gID}
}
}
exports.getFeeds = async (req, res)=>
{
var payload = await feedsM.find({gID:req.headers.guildid}).then(res=>{return res}).catch(err=>{return err});
res.json(payload)
}
exports.getFeed = async (req, res)=>
{
var payload = await feedsM.find({_id:req.headers.feedid}).then(res=>{return res}).catch(err=>{return err});
res.json(payload)
}
exports.getChannelName = async (req,res)=>
{
var payload = await fetch('https://www.youtube.com/feeds/videos.xml?channel_id='+req.headers.channelid,
{
method: "GET",
mode: "cors",
})
.then(response=>
{
if(response.ok) return response.text();
})
.then(data=>
{
data = xmlparser.xml2json(data,
{
compact: true,
space: 4
});
data = JSON.parse(data);
return data.feed.author.name._text
})
.catch(error=>
{
return error;
});
res.json(payload);
}
exports.addFeed = (bot)=>
{
return async (req, res)=>
{
var headers= req.headers;
var args = [headers.gid, headers.dcchannelid, headers.ytchannelid]
const validationResult = await confirmArgs(args, bot);
if(headers.isnew=="true")
{
if (validationResult.error) return res.json({error:validationResult.error})
var feed = new feedsM();
feed.gID = headers.gid;
feed.ChannelId = validationResult.channelId
feed.YTChannelId = validationResult.YTChannelId;
feed.CostumMessage = headers.costummessagei!=''?headers.costummessagei:'New video:';
feed.save(err=>
{
if(err)res.json({error:err});
res.json({success:true, feed})
})
}
else
{
feedsM.findOne({id:args.id}).then(feed=>
{
console.log('here', feed)
if(!feed) return res.json({error:'DB Error'});
feed.gID = headers.gid;
feed.ChannelId = validationResult.channelId
feed.YTChannelId = validationResult.YTChannelId;
feed.CostumMessage = headers.costummessagei!=''?headers.costummessagei:'New video:';
feedsM.updateOne({_id:feed.id}, feed,{upsert:true}).then(updatedG=>
{
res.json({success:true, feed})
})
})
}
}
}
async function confirmArgs(args, bot)
{
var channelId = args[1];
var channelURL = args[2]
async function getChannelId(url)
{
if(url.split('@').length<1) return false
return await fetch(url)
.then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response)
{
if(response.ok) return response.text();
}
function handleError(error)
{
return error;
}
function handleData(data)
{
return data ? data.split('https://www.youtube.com/feeds/videos.xml?channel_id=')[1].split('"')[0] : false;
}
}
const YTChannelId = await getChannelId(channelURL);
const exists = await bot.channels.fetch(channelId).then(channel=>{return channel }).catch(()=>{return null});
if(!exists) return {error:'Provided channel id does not exist.'}
var name = await fetch(`https://www.youtube.com/feeds/videos.xml?channel_id=${YTChannelId}`)
.then(response =>
{
return response.text()
})
.then(data=>
{
data = xmlparser.xml2json(data,
{
compact: true,
space: 4
});
data = JSON.parse(data);
return data.feed.author.name._text
})
.catch(error=>{return error;});
if(!name) return {error:'Provided Youtube channel does not exist.'}
const channelInUse = await feedsM.findOne({ChannelId:channelId}).then(channel=>{return channel}).catch(()=>{return []});
if(channelInUse) return {error:'Discord channel already in use. Please choose another.'}
return {YTChannelId, channelId, name, channelName:exists.name}
}
exports.deleteFeed = (req,res) =>
{
feedsM.findOneAndDelete({_id:req.headers.feedid}).then(()=>{res.json({success:true})}).catch(error=>{res.json({error})})
}

@ -7,6 +7,7 @@ new Schema(
ChannelId: {type:String, required: true},
YTChannelId: {type:String, required: true},
CostumMessage:{type:String, required:false},
gID:{type:String, required:false},
}
);

@ -339,7 +339,6 @@ body {
aspect-ratio: 16/9;
position:absolute;
top:-50%;
left:0;
font-size:1em;
top:50%;
left:50%;
@ -415,7 +414,6 @@ p
{
font-weight:bold;
font-family: 'Lato';
}
input
{
@ -484,3 +482,105 @@ input
margin-top:0.5em;
cursor:pointer;
}
#ChannelName
{
position: absolute;
color: ivory;
top: 1.5vh;
left: 50%;
transform: translateX(-50%);
font-family: 'lato';
}
.FeedWrapper
{
height: 20em;
aspect-ratio: 16/9;
border: 1px solid ivory;
position:absolute;
top:50%;
left:50%;
font-size:1em;
font-family:'lato';
color:ivory;
transform: translateX(-50%) translateY(-50%);
text-align:center;
border-radius: 10px;
overflow: hidden;
background-color:#5a8786;
}
.channel
{
position:absolute;
top:50%;
}
.labeldc
{
left:10%
}
.labelyt
{
right:10%
}
.dc
{
left:10%;
transform:translateY(250%);
background-color:#00000054;
border:2px solid transparent;
color:ivory;
text-align:right;
width: 37.5%;
}
.yt
{
right:10%;
transform:translateY(250%);
background-color:#00000054;
border:2px solid transparent;
color:ivory;
text-align:right;
width: 37.5%;
}
.feeds
{
border: 2px solid #020608;
height: 20vh;
position: absolute;
top:1%;
overflow-y: scroll;
width: 60%;
left: 20%;
background-color:#071c24de;
color: ivory;
border-radius: 5px;
}
.rules p
{
cursor: pointer;
}
.feeds p
{
cursor: pointer;
}
.message
{
position: absolute;
top: 20%;
}
.CostumMessage
{
color:ivory;
}
.CostumMessageI
{
transform: translateY(80%);
background-color: #00000054;
border: 2px solid transparent;
color: ivory;
text-overflow: wrap;
width: 37.5%;
height: 4em;
resize: none;
}

@ -71,7 +71,7 @@ function handleSettigns(event)
function handleClose(element)
{
if(element.parentNode.id == 'roleRuleWrapper') document.getElementById('popup').classList.remove('hidden');
if(element.parentNode.id == 'roleRuleWrapper' || element.parentNode.id == 'FeedWrapper') document.getElementById('popup').classList.remove('hidden');
element.parentNode.classList.add('hidden');
}
async function requestChange()
@ -178,13 +178,103 @@ async function handleToggleRules(element)
<i onclick="handleClose(this)" class="close material-symbols-outlined" id="close_bt">
cancel
</i>
<p id="newRole" onclick="addRule(this)">New Role</p>
<p id="newRole" onclick="addRule(this)">New Rule</p>
${ruleArr.join('')}
`
rulesElement.classList.remove('hidden')
}
function handleToggleFeeds(element)
async function getFeeds(gid)
{
return await fetch(`${window.location.origin}/api/getFeeds`,
{
method: "GET",
mode: "cors",
headers: {guildid:gid},
})
.then(result => result.json())
.then(res =>
{
return res
})
.catch(console.error);
}
async function getFeed(feedID)
{
return await fetch(`${window.location.origin}/api/getFeed`,
{
method: "GET",
mode: "cors",
headers: {feedID},
})
.then(result => result.json())
.then(res =>
{
return res[0]
})
.catch(console.error);
}
async function getChannelID(id)
{
if(url.split('@').length<1) return false
return await fetch(url)
.then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response)
{
if(response.ok) return response.text();
}
function handleError(error)
{
return error;
}
function handleData(data)
{
return data ? data.split('https://www.youtube.com/feeds/videos.xml?channel_id=')[1].split('"')[0] : false;
}
}
async function getChannelName(channelID)
{
return await fetch(`${window.location.origin}/api/getChannelName`,
{
method: "GET",
mode: "cors",
headers: {channelID},
})
.then(response=>
{
if(response.ok) return response.text();
})
.then(data=>
{
return data.replaceAll('"','')
})
.catch(error=>
{
return error;
});
}
async function handleToggleFeeds(element)
{
var guildID = element.parentNode.getElementsByTagName('h3')[0].id;
var feedElement=document.getElementById('feeds');
var feeds = await getFeeds(guildID);
if(!feeds) return
var ruleArr = [];
for (let i = 0; i < feeds.length; i++) {
var ytchannelname = await getChannelName(feeds[i].YTChannelId)
ruleArr.push(`<p id="${feeds[i]._id}" onclick="updateFeed(this)">${ytchannelname}</p>`)
}
feedElement.innerHTML = `
<i onclick="handleClose(this)" class="close material-symbols-outlined" id="close_bt">
cancel
</i>
<p id="newFeed" onclick="addFeed(this)">New Feed</p>
${ruleArr.join('')}
`
feedElement.classList.remove('hidden');
}
function deleteRule(element)
@ -242,7 +332,6 @@ function updateRule(element)
.then(result => result.json())
.then(res =>
{
console.log(res);
if(res.success)
{
element.parentNode.classList.add('hidden')
@ -294,9 +383,88 @@ async function changeRule(element)
ruleWrapper.classList.remove('hidden');
document.getElementsByClassName('roleRuleWrapper')[0].setAttribute('data-before', message)
document.getElementById('roleRule').innerText = rule.roleName;
document.getElementById('roleRule').classList = 'roleRule';
document.getElementById('roleRule').classList.add(rule._id);
document.getElementById('roleID').placeholder = rule.roleID;
document.getElementById('emojiID').placeholder = rule.roleEmoji;
document.getElementById('messageID').placeholder = rule.mID;
document.getElementById('roleID').value = rule.roleID;
document.getElementById('emojiID').value = rule.roleEmoji;
document.getElementById('messageID').value = rule.mID;
document.getElementById('emojiImg').src = `https://cdn.discordapp.com/emojis/${rule.roleEmoji}.webp`;
}
function addFeed(element)
{
element.parentNode.classList.add('hidden');
element.parentNode.parentNode.classList.add('hidden');
var FeedWrapper = document.getElementById('FeedWrapper');
FeedWrapper.classList.remove('hidden');
document.getElementById('ChannelName').innerText = 'New Feed'
document.getElementById('DCchannelID').placeholder = '';
document.getElementById('YTchannelID').placeholder = '';
document.getElementById('CostumMessageI').placeholder = '';
}
async function updateFeed(element)
{
var feed = await getFeed(element.id)
element.parentNode.classList.add('hidden');
element.parentNode.parentNode.classList.add('hidden');
var FeedWrapper = document.getElementById('FeedWrapper');
FeedWrapper.classList.remove('hidden');
document.getElementById('ChannelName').innerText = element.textContent;
document.getElementById('ChannelName').classList ='';
document.getElementById('ChannelName').classList.add(element.id);
document.getElementById('DCchannelID').value = feed.ChannelId;
document.getElementById('YTchannelID').value = feed.YTChannelId;
document.getElementById('CostumMessageI').value = feed.CostumMessage;
}
function deleteFeed(element)
{
var feedID = document.getElementById('ChannelName').classList[1];
fetch(`${window.location.origin}/api/deleteFeed`,
{
method: "POST",
mode: "cors",
headers: {feedID},
})
.then(result => result.json())
.then(res =>
{
if(res.success)
{
element.parentNode.classList.add('hidden')
document.getElementById('popup').classList.remove('hidden');
}
else alert(res.error);
})
.catch(console.error);
}
function _updateFeed(element)
{
var isNew=false;
if(element.parentNode.children[1].innerText == 'New Feed') isNew = true;
var feedID;
if(!isNew) feedID = document.getElementById('ChannelName').classList[1];
console.log('fid', feedID)
var gid = document.getElementsByClassName('guildname')[0].id;
console.log('gid', gid)
var DCchannelID = document.getElementById('DCchannelID').value;
var YTchannelID = document.getElementById('YTchannelID').value;
var CostumMessageI = document.getElementById('CostumMessageI').value;
fetch(`${window.location.origin}/api/addFeed`,
{
method: "POST",
mode: "cors",
headers: {DCchannelID, YTchannelID, CostumMessageI, gid,isNew, feedID},
})
.then(result => result.json())
.then(res =>
{
if(res.success)
{
element.parentNode.classList.add('hidden')
document.getElementById('popup').classList.remove('hidden');
}
else alert(res.error);
})
.catch(console.error);
}

@ -9,7 +9,13 @@ module.exports = (io, bot)=>
router.route('/api/getGuildData/').post(api.guildData(io, bot));
router.route('/api/Change/').post(api.updateGuild(io));
router.route('/api/getRules').get(api.getRules);
router.route('/api/getFeeds').get(api.getFeeds);
router.route('/api/getFeed').get(api.getFeed);
router.route('/api/deleteFeed').post(api.deleteFeed);
router.route('/api/addFeed').post(api.addFeed(bot));
router.route('/api/updateFeed').post(api.addFeed(bot));
router.route('/api/getMessage').get(api.getMessage(bot));
router.route('/api/getChannelName').get(api.getChannelName);
router.route('/api/updateRule').post(api.updateRule(bot));
router.route('/api/deleteRule').post(api.deleteRule);
router.route('/dashboard').get(dash.get(io))

@ -35,12 +35,11 @@
<p id="RoleRules" onclick="handleToggleRules(this)">Role rules</p>
<p id="Feeds" onclick="handleToggleFeeds(this)">Feeds</p>
<div id="rules" class="rules hidden">
<i onclick="handleClose(this)" class="close material-symbols-outlined" id="close_bt">
cancel
</i>
<p id="newRole" onclick="addRule(this)">New Role</p>
<p id="ruleID" class="addRoleName">Role Name</p>
</div>
<div id="feeds" class="feeds hidden">
</div>
</div>
<div id="roleRuleWrapper"class="roleRuleWrapper hidden">
<i onclick="handleClose(this)" class="close material-symbols-outlined" id="close_bt2">
@ -56,18 +55,20 @@
<button id="change" class="bt" onclick='updateRule(this)'>Change</button>
<button id="delete" class="bt" onclick='deleteRule(this)'>Delete</button>
</div>
<!--
RoleRules
Channels
Feeds
-->
<div id="FeedWrapper" class="FeedWrapper hidden">
<h1 id="ChannelName">Feed</h1>
<i onclick="handleClose(this)" class="close material-symbols-outlined" id="close_bt2">
cancel
</i>
<p id='DCchannel' class="channel labeldc">Discord Channel:</p>
<p id="YTchannel" class="channel labelyt">Youtube Channel:</p>
<p id="CostumMessage" class="message CostumMessage">Costum message:</p>
<input id ="DCchannelID" class='channel dc'></input>
<input id ="YTchannelID" class='channel yt'></input>
<textarea id="CostumMessageI" class='message CostumMessageI' cols="40" rows="5"></textarea>
<button id="delete" class="bt" onclick='deleteFeed(this)'>Delete</button>
<button id="change" class="bt" onclick='_updateFeed(this)'>Change</button>
</div>
</body>
</html>

Loading…
Cancel
Save