Browse Source

Cleanup?

Former-commit-id: 38024dfa8a
master
Yiğit Çolakoğlu 5 years ago
parent
commit
7cf7501486
90 changed files with 8865 additions and 7 deletions
  1. +10
    -0
      .gitignore
  2. +0
    -1
      .gitignore.REMOVED.git-id
  3. BIN
      .gitsecret/keys/pubring.kbx
  4. +0
    -1
      .gitsecret/keys/pubring.kbx.REMOVED.git-id
  5. BIN
      .gitsecret/keys/pubring.kbx~
  6. +0
    -1
      .gitsecret/keys/pubring.kbx~.REMOVED.git-id
  7. BIN
      .gitsecret/keys/trustdb.gpg
  8. +0
    -1
      .gitsecret/keys/trustdb.gpg.REMOVED.git-id
  9. +6
    -0
      .gitsecret/paths/mapping.cfg
  10. +0
    -1
      .gitsecret/paths/mapping.cfg.REMOVED.git-id
  11. +2
    -0
      README.md
  12. +0
    -1
      README.md.REMOVED.git-id
  13. +23
    -0
      docker-compose.yml
  14. +0
    -1
      docker-compose.yml.REMOVED.git-id
  15. BIN
      init_db.sql.secret
  16. +1
    -0
      xi_comic/.gitignore
  17. +15
    -0
      xi_comic/Dockerfile
  18. +16
    -0
      xi_comic/commands/comic.js
  19. +21
    -0
      xi_comic/commands/hail_mary.js
  20. +66
    -0
      xi_comic/main.js
  21. +1001
    -0
      xi_comic/package-lock.json
  22. +15
    -0
      xi_comic/package.json
  23. +2
    -0
      xi_music/.dockerignore
  24. +1
    -0
      xi_music/.gitignore
  25. +18
    -0
      xi_music/Dockerfile
  26. +16
    -0
      xi_music/client.js
  27. +71
    -0
      xi_music/commands/malatya.js
  28. +9
    -0
      xi_music/commands/nowplaying.js
  29. +88
    -0
      xi_music/commands/play.js
  30. +117
    -0
      xi_music/commands/playlist.js
  31. +20
    -0
      xi_music/commands/queue.js
  32. BIN
      xi_music/commands/secrets.json.secret
  33. +11
    -0
      xi_music/commands/skip.js
  34. +11
    -0
      xi_music/commands/stop.js
  35. +71
    -0
      xi_music/commands/swat.js
  36. +100
    -0
      xi_music/main.js
  37. +1528
    -0
      xi_music/package-lock.json
  38. +22
    -0
      xi_music/package.json
  39. +1
    -0
      xi_news/.gitignore
  40. +18
    -0
      xi_news/Dockerfile
  41. +16
    -0
      xi_news/client.js
  42. +16
    -0
      xi_news/commands/crawler.js
  43. +36
    -0
      xi_news/commands/get_rss.js
  44. +278
    -0
      xi_news/commands/jFeed-master/GPL-license.txt
  45. +20
    -0
      xi_news/commands/jFeed-master/MIT-license.txt
  46. +40
    -0
      xi_news/commands/jFeed-master/Makefile
  47. +47
    -0
      xi_news/commands/jFeed-master/README.mediawiki
  48. +170
    -0
      xi_news/commands/jFeed-master/build/dist/jquery.jfeed.js
  49. +1
    -0
      xi_news/commands/jFeed-master/build/dist/jquery.jfeed.pack.js
  50. +467
    -0
      xi_news/commands/jFeed-master/build/packer/Pack.pm
  51. +207
    -0
      xi_news/commands/jFeed-master/build/packer/ParseMaster.pm
  52. +163
    -0
      xi_news/commands/jFeed-master/build/packer/jsPacker.pl
  53. +65
    -0
      xi_news/commands/jFeed-master/example-proxy.html
  54. +65
    -0
      xi_news/commands/jFeed-master/example.html
  55. +4
    -0
      xi_news/commands/jFeed-master/jquery/jquery.js
  56. +12
    -0
      xi_news/commands/jFeed-master/proxy.php
  57. +36
    -0
      xi_news/commands/jFeed-master/src/jatom.js
  58. +85
    -0
      xi_news/commands/jFeed-master/src/jfeed.js
  59. +11
    -0
      xi_news/commands/jFeed-master/src/jfeeditem.js
  60. +38
    -0
      xi_news/commands/jFeed-master/src/jrss.js
  61. +54
    -0
      xi_news/commands/jFeed-master/test-dist-packed.html
  62. +54
    -0
      xi_news/commands/jFeed-master/test-dist.html
  63. +64
    -0
      xi_news/commands/jFeed-master/test-src.html
  64. +157
    -0
      xi_news/commands/jFeed-master/xml/atom.xml
  65. +54
    -0
      xi_news/commands/jFeed-master/xml/rss-091.xml
  66. +38
    -0
      xi_news/commands/jFeed-master/xml/rss-092.xml
  67. +53
    -0
      xi_news/commands/jFeed-master/xml/rss-10.xml
  68. +47
    -0
      xi_news/commands/jFeed-master/xml/rss-20.xml
  69. +2
    -0
      xi_news/commands/jquery-3.5.1.min.js
  70. +67
    -0
      xi_news/main.js
  71. +1163
    -0
      xi_news/package-lock.json
  72. +28
    -0
      xi_news/package.json
  73. +1
    -0
      xi_tracker/.gitignore
  74. +15
    -0
      xi_tracker/Dockerfile
  75. +28
    -0
      xi_tracker/Locations list.txt
  76. +16
    -0
      xi_tracker/client.js
  77. +27
    -0
      xi_tracker/commands/down.js
  78. +94
    -0
      xi_tracker/commands/email.js
  79. +45
    -0
      xi_tracker/commands/role_message.js
  80. +26
    -0
      xi_tracker/commands/schemas.js
  81. +53
    -0
      xi_tracker/commands/team_close.js
  82. +159
    -0
      xi_tracker/commands/team_create.js
  83. +77
    -0
      xi_tracker/commands/team_elevate.js
  84. +103
    -0
      xi_tracker/commands/team_kick.js
  85. +81
    -0
      xi_tracker/commands/team_lower.js
  86. +87
    -0
      xi_tracker/commands/team_quit.js
  87. +90
    -0
      xi_tracker/commands/team_user.js
  88. +28
    -0
      xi_tracker/commands/up.js
  89. +282
    -0
      xi_tracker/main.js
  90. +815
    -0
      xi_tracker/package-lock.json

+ 10
- 0
.gitignore View File

@ -0,0 +1,10 @@
*/node_modules
.gitsecret/keys/random_seed
!*.secret
.keys
xi_tracker/config.json
xi_music/config.json
xi_music/commands/secrets.json
xi_comic/config.json
xi_news/config.json
init_db.sql

+ 0
- 1
.gitignore.REMOVED.git-id View File

@ -1 +0,0 @@
4061bfee1f8bf7ebbca3e333ec8581d6be602270

BIN
.gitsecret/keys/pubring.kbx View File


+ 0
- 1
.gitsecret/keys/pubring.kbx.REMOVED.git-id View File

@ -1 +0,0 @@
4cd1427e35ec41e32dde2f395bd2292dd6051083

BIN
.gitsecret/keys/pubring.kbx~ View File


+ 0
- 1
.gitsecret/keys/pubring.kbx~.REMOVED.git-id View File

@ -1 +0,0 @@
3a4903efb68cb10057d70a224d4733bd0bdc56e3

BIN
.gitsecret/keys/trustdb.gpg View File


+ 0
- 1
.gitsecret/keys/trustdb.gpg.REMOVED.git-id View File

@ -1 +0,0 @@
f6aabe81009919d25685b217dc9595d299b3cad9

+ 6
- 0
.gitsecret/paths/mapping.cfg View File

@ -0,0 +1,6 @@
init_db.sql:bb32c3ee705a5a16e99e50eac4f86ec1e2f0efef1f9fb998facc67d124413701
xi_comic/config.json:24c8698513b2f855744e2410997c9f2eb68aeefb74ad274106f864760124a13b
xi_music/config.json:ce1527843326f34840ee04a12c3c49ade15d0005fc0db9aa4000298ca99ca62d
xi_tracker/config.json:b7610c60037babef2858c1dbba1b87e1fec0014d79e75889d4c55565055d5ce0
xi_music/commands/secrets.json:12f928314c51e905c3ef74fc5c15914908151f0d73d7c337493b8413701fc172
xi_news/config.json:e883fb5c1b71d938bca202c5731a77bce4296ab4076ede59b4e15fb61377e37a

+ 0
- 1
.gitsecret/paths/mapping.cfg.REMOVED.git-id View File

@ -1 +0,0 @@
9607cf402ec246f9a4baa64027e1cb1eaac35f06

+ 2
- 0
README.md View File

@ -0,0 +1,2 @@
# xi-bots
A group of bots to use in our private discord server.

+ 0
- 1
README.md.REMOVED.git-id View File

@ -1 +0,0 @@
c49e104ab5d78bf11d51e12583ed1e8bdf5e7add

+ 23
- 0
docker-compose.yml View File

@ -0,0 +1,23 @@
version: "3.7"
services:
xi_music:
build:
context: ./xi_music
dockerfile: Dockerfile
container_name: xi_music_bot
image: fr1nge/xi_music:latest
xi_comic:
build:
context: ./xi_comic
dockerfile: Dockerfile
container_name: xi_comic_bot
image: fr1nge/xi_comic:latest
xi_ranker:
build:
context: ./xi_ranker
dockerfile: Dockerfile
container_name: xi_ranker_bot
image: fr1nge/xi_ranker:latest

+ 0
- 1
docker-compose.yml.REMOVED.git-id View File

@ -1 +0,0 @@
088bca44a4ac179bf61d0c242e2a954dcec005c0

BIN
init_db.sql.secret View File


+ 1
- 0
xi_comic/.gitignore View File

@ -0,0 +1 @@
node_modules

+ 15
- 0
xi_comic/Dockerfile View File

@ -0,0 +1,15 @@
FROM node:lts
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
# If you are building your code for production
# # RUN npm ci --only=production
COPY . .
CMD [ "node", "main.js" ]

+ 16
- 0
xi_comic/commands/comic.js View File

@ -0,0 +1,16 @@
const xkcd = require('xkcd-api');
module.exports = {
name: 'comic',
description: 'Send a random xkcd comic.',
execute(message) {
var message = message;
xkcd.random(function(error, response) {
if (error) {
console.error(error);
} else {
message.channel.send(`**${response.safe_title}**\n*${response.alt}*`, {files: [response.img]})
}
});
},
};

+ 21
- 0
xi_comic/commands/hail_mary.js View File

@ -0,0 +1,21 @@
const xkcd = require('xkcd-api');
module.exports = {
name: 'hail_mary',
description: 'Fuck everyone\'s chat up by sneding a random number of comics between 0-3.',
roles: ['732345527143759943'],
execute(message) {
var message = message;
message.channel.send("Initiating comic hail mary!")
for(i = 0; i < Math.floor(Math.random() * (30 - 0) + 0); i++){
xkcd.random(function(error, response) {
if (error) {
console.error(error);
} else {
message.channel.send(`**${response.safe_title}**\n*${response.alt}*`, {files: [response.img]})
}
});
}
},
};

+ 66
- 0
xi_comic/main.js View File

@ -0,0 +1,66 @@
const fs = require('fs')
const Discord = require('discord.js');
const { Client, Collection } = require('discord.js');
const {
prefix,
token,
} = require('./config.json');
const client = new Client();
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
console.log(client.commands);
client.once('ready', () => {
console.log('Ready!');
});
client.once('reconnecting', () => {
console.log('Reconnecting!');
});
client.once('disconnect', () => {
console.log('Disconnect!');
});
client.on('message', async message => {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) return;
const command = client.commands.get(commandName);
const permitted_roles = client.commands.get(commandName)["roles"];
has_roles = false
if (permitted_roles){
for(i = 0; i < permitted_roles.length; i++){
if(message.member.roles.cache.has(permitted_roles[i])){
has_roles = true
}
}
if (!has_roles && permitted_roles.length != 0){
message.reply('You are not allowed to run this command!');
return;
}
}
try {
command.execute(message);
} catch (error) {
console.error(error);
message.reply('There was an error trying to execute that command!');
}
});
client.login(token);

+ 1001
- 0
xi_comic/package-lock.json
File diff suppressed because it is too large
View File


+ 15
- 0
xi_comic/package.json View File

@ -0,0 +1,15 @@
{
"name": "xi_master",
"version": "1.0.0",
"description": "A master music bot for our xi network discord server",
"author": "Fringe <yigit@yigitcolakoglu.com>",
"main": "main.js",
"scripts": {
"start": "node main.js"
},
"dependencies": {
"discord.js": "^12.2.0",
"sqlite3": "^5.0.0",
"xkcd-api": "^1.2.0"
}
}

+ 2
- 0
xi_music/.dockerignore View File

@ -0,0 +1,2 @@
node_modules
npm-debug.log

+ 1
- 0
xi_music/.gitignore View File

@ -0,0 +1 @@
node_modules

+ 18
- 0
xi_music/Dockerfile View File

@ -0,0 +1,18 @@
FROM node:lts
RUN apt-get update || : && apt-get install python -y
RUN apt-get install ffmpeg -y
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
# If you are building your code for production
# # RUN npm ci --only=production
COPY . .
CMD [ "node", "main.js" ]

+ 16
- 0
xi_music/client.js View File

@ -0,0 +1,16 @@
const { Client, Collection } = require('discord.js');
module.exports = class extends Client {
constructor(config) {
super({
disableEveryone: true,
disabledEvents: ['TYPING_START'],
});
this.commands = new Collection();
this.queue = new Map();
this.config = config;
}
};

+ 71
- 0
xi_music/commands/malatya.js View File

@ -0,0 +1,71 @@
const ytdl = require("ytdl-core");
module.exports = {
name: 'malatya',
description: 'SWAT',
roles: ['732345527143759943'],
async execute(message){
const queue = message.client.queue;
const serverQueue = message.client.queue.get(message.guild.id);
const voiceChannel = message.member.voice.channel;
if (!voiceChannel)
return message.channel.send(
"You need to be in a voice channel to SWAT!"
);
if(serverQueue){
while(serverQueue.songs[0]){
serverQueue.songs.shift();
}
serverQueue.songs.push({});
serverQueue.songs.push({title: "MALATYA", url: "https://www.youtube.com/watch?v=qyczHCg2zhw"});
serverQueue.connection.dispatcher.end();
}else{
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: 5,
playing: true
};
queue.set(message.guild.id, queueContruct);
queueContruct.songs.push({title: "MALATYA", url: "https://www.youtube.com/watch?v=qyczHCg2zhw"});
try {
var connection = await voiceChannel.join();
queueContruct.connection = connection;
this.play(message, queueContruct.songs[0]);
} catch (err) {
console.log(err);
queue.delete(message.guild.id);
return message.channel.send(err);
}
}
},
play(message, song) {
const queue = message.client.queue;
const guild = message.guild;
const serverQueue = queue.get(message.guild.id);
if (!song) {
serverQueue.voiceChannel.leave();
queue.delete(guild.id);
return;
}
const dispatcher = serverQueue.connection
.play(ytdl(song.url, { filter: 'audioonly', highWaterMark: 1024 * 1024 * 10 }))
.on("finish", () => {
serverQueue.songs.shift();
this.play(message, serverQueue.songs[0]);
})
.on("error", error => console.error(error));
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
serverQueue.textChannel.send(`Start playing: **${song.title}**`);
},
};

+ 9
- 0
xi_music/commands/nowplaying.js View File

@ -0,0 +1,9 @@
module.exports = {
name: 'nowplaying',
description: 'Get the song that is playing.',
execute(message) {
const serverQueue = message.client.queue.get(message.guild.id);
if (!serverQueue) return message.channel.send('There is nothing playing.');
return message.channel.send(`Now playing: ${serverQueue.songs[0].title}`);
},
};

+ 88
- 0
xi_music/commands/play.js View File

@ -0,0 +1,88 @@
const ytdl = require("ytdl-core");
module.exports = {
name: "play",
description: "Play a song in your channel!",
roles: ['732550362199752764', '732345527143759943'],
async execute(message) {
try {
const args = message.content.split(" ");
const queue = message.client.queue;
const serverQueue = message.client.queue.get(message.guild.id);
const voiceChannel = message.member.voice.channel;
if (!voiceChannel)
return message.channel.send(
"You need to be in a voice channel to play music!"
);
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has("CONNECT") || !permissions.has("SPEAK")) {
return message.channel.send(
"I need the permissions to join and speak in your voice channel!"
);
}
const songInfo = await ytdl.getInfo(args[1]);
const song = {
title: songInfo.videoDetails.title,
url: songInfo.videoDetails.video_url
};
if (!serverQueue) {
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: 5,
playing: true
};
queue.set(message.guild.id, queueContruct);
queueContruct.songs.push(song);
try {
var connection = await voiceChannel.join();
queueContruct.connection = connection;
this.play(message, queueContruct.songs[0]);
} catch (err) {
console.log(err);
queue.delete(message.guild.id);
return message.channel.send(err);
}
} else {
serverQueue.songs.push(song);
return message.channel.send(
`${song.title} has been added to the queue!`
);
}
} catch (error) {
console.log(error);
message.channel.send(error.message);
}
},
play(message, song) {
const queue = message.client.queue;
const guild = message.guild;
const serverQueue = queue.get(message.guild.id);
if (!song) {
serverQueue.voiceChannel.leave();
queue.delete(guild.id);
return;
}
const dispatcher = serverQueue.connection
.play(ytdl(song.url, { filter: 'audioonly', highWaterMark: 1024 * 1024 * 10 }))
.on("finish", () => {
serverQueue.songs.shift();
this.play(message, serverQueue.songs[0]);
})
.on("error", error => console.error(error));
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
serverQueue.textChannel.send(`Start playing: **${song.title}**`);
}
};

+ 117
- 0
xi_music/commands/playlist.js View File

@ -0,0 +1,117 @@
const { google } = require('googleapis');
const youtube = google.youtube('v3');
const secrets = require('./secrets.json');
const ytdl = require("ytdl-core");
module.exports = {
name: 'playlist',
description: 'Add playlist to the queue.',
roles: ['732550362199752764', '732345527143759943'],
async execute(message) {
var message = message;
const args = message.content.split(" ");
try{
let playlist_id = args[1].match(/https:\/\/www\.youtube\.com\/watch\?.*list=(.{34}).*/)[1]
youtube.playlistItems.list({
key: secrets.web.api_key,
part: 'snippet, contentDetails',
playlistId: playlist_id,
maxResults: 50,
}, async (err, results) => {
try {
const queue = message.client.queue;
const serverQueue = message.client.queue.get(message.guild.id);
const voiceChannel = message.member.voice.channel;
if (!voiceChannel)
return message.channel.send(
"You need to be in a voice channel to play music!"
);
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has("CONNECT") || !permissions.has("SPEAK")) {
return message.channel.send(
"I need the permissions to join and speak in your voice channel!"
);
}
if (!serverQueue) {
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: 5,
playing: true
};
queue.set(message.guild.id, queueContruct);
results.data.items.forEach(function(item, index){
url = "https://www.youtube.com/watch?v=" + item.contentDetails.videoId
let song = {
title: item.snippet.title,
url: url
};
queueContruct.songs.push(song);
});
try {
var connection = await voiceChannel.join();
queueContruct.connection = connection;
this.play(message, queueContruct.songs[0]);
} catch (err) {
console.log(err);
queue.delete(message.guild.id);
return message.channel.send(err);
}
return message.channel.send(
`Playing the first song from the playlist!`
);
} else {
results.data.items.forEach(function(item, index){
url = "https://www.youtube.com/watch?v=" + item.contentDetails.videoId
let song = {
title: item.snippet.title,
url: url
};
serverQueue.songs.push(song);
});
return message.channel.send(
`Added songs from the playlist to the queue!`
);
}
} catch (error) {
console.log(error);
message.channel.send("Sorry, that did not work for some mysterious reason :(");
}
});
} catch (error) {
console.log(error);
message.channel.send("Sorry, that did not work for some mysterious reason :(");
}
},
play(message, song) {
const queue = message.client.queue;
const guild = message.guild;
const serverQueue = queue.get(message.guild.id);
if (!song) {
serverQueue.voiceChannel.leave();
queue.delete(guild.id);
return;
}
const dispatcher = serverQueue.connection
.play(ytdl(song.url, { filter: 'audioonly', highWaterMark: 1024 * 1024 * 10 }))
.on("finish", () => {
serverQueue.songs.shift();
this.play(message, serverQueue.songs[0]);
})
.on("error", error => console.error(error));
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
serverQueue.textChannel.send(`Start playing: **${song.title}**`);
},
};

+ 20
- 0
xi_music/commands/queue.js View File

@ -0,0 +1,20 @@
module.exports = {
name: 'queue',
description: 'Display the queue for the next items',
execute(message) {
const serverQueue = message.client.queue.get(message.guild.id);
if (!serverQueue) return message.channel.send('There is nothing in queue.');
message_txt = `There are ${serverQueue.songs.length} items on the list\n`
message_txt += "```\n";
c = 0
serverQueue.songs.forEach(function (item, index){
if(c == 10){
return;
}
c += 1;
message_txt += `${index}: ${item.title}\n`
})
message_txt += "\n```";
return message.channel.send(message_txt);
},
};

BIN
xi_music/commands/secrets.json.secret View File


+ 11
- 0
xi_music/commands/skip.js View File

@ -0,0 +1,11 @@
module.exports = {
name: 'skip',
description: 'Skip a song!',
roles: ['732550362199752764', '732345527143759943'],
execute(message) {
const serverQueue = message.client.queue.get(message.guild.id);
if (!message.member.voice.channel) return message.channel.send('You have to be in a voice channel to stop the music!');
if (!serverQueue) return message.channel.send('There is no song that I could skip!');
serverQueue.connection.dispatcher.end();
},
};

+ 11
- 0
xi_music/commands/stop.js View File

@ -0,0 +1,11 @@
module.exports = {
name: 'stop',
description: 'Stop all songs in the queue!',
roles: ['732550362199752764', '732345527143759943'],
execute(message) {
const serverQueue = message.client.queue.get(message.guild.id);
if (!message.member.voice.channel) return message.channel.send('You have to be in a voice channel to stop the music!');
serverQueue.songs = [];
serverQueue.connection.dispatcher.end();
},
};

+ 71
- 0
xi_music/commands/swat.js View File

@ -0,0 +1,71 @@
const ytdl = require("ytdl-core");
module.exports = {
name: 'swat',
description: 'SWAT',
roles: ['732345527143759943'],
async execute(message){
const queue = message.client.queue;
const serverQueue = message.client.queue.get(message.guild.id);
const voiceChannel = message.member.voice.channel;
if (!voiceChannel)
return message.channel.send(
"You need to be in a voice channel to SWAT!"
);
if(serverQueue){
while(serverQueue.songs[0]){
serverQueue.songs.shift();
}
serverQueue.songs.push({});
serverQueue.songs.push({title: "SWAT", url: "https://www.youtube.com/watch?v=kNynwelr8ps"});
serverQueue.connection.dispatcher.end();
}else{
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: 5,
playing: true
};
queue.set(message.guild.id, queueContruct);
queueContruct.songs.push({title: "SWAT", url: "https://www.youtube.com/watch?v=kNynwelr8ps"});
try {
var connection = await voiceChannel.join();
queueContruct.connection = connection;
this.play(message, queueContruct.songs[0]);
} catch (err) {
console.log(err);
queue.delete(message.guild.id);
return message.channel.send(err);
}
}
},
play(message, song) {
const queue = message.client.queue;
const guild = message.guild;
const serverQueue = queue.get(message.guild.id);
if (!song) {
serverQueue.voiceChannel.leave();
queue.delete(guild.id);
return;
}
const dispatcher = serverQueue.connection
.play(ytdl(song.url, { filter: 'audioonly', highWaterMark: 1024 * 1024 * 10 }))
.on("finish", () => {
serverQueue.songs.shift();
this.play(message, serverQueue.songs[0]);
})
.on("error", error => console.error(error));
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
serverQueue.textChannel.send(`Start playing: **${song.title}**`);
},
};

+ 100
- 0
xi_music/main.js View File

@ -0,0 +1,100 @@
const fs = require('fs')
const Discord = require('discord.js');
const Client = require('./client');
const {
prefix,
token,
} = require('./config.json');
const client = new Client();
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
console.log(client.commands);
client.once('ready', () => {
console.log('Ready!');
});
client.once('reconnecting', () => {
console.log('Reconnecting!');
});
client.once('disconnect', () => {
console.log('Disconnect!');
});
client.on('message', async message => {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) return;
const command = client.commands.get(commandName);
const permitted_roles = client.commands.get(commandName)["roles"];
const permitted_channels = client.commands.get(commandName)["channels"]
has_roles = false
if (permitted_roles){
for(i = 0; i < permitted_roles.length; i++){
if(message.member.roles.cache.has(permitted_roles[i])){
has_roles = true
}
}
if (!has_roles && permitted_roles.length != 0){
message.reply('You are not allowed to run this command!');
return;
}
}
if (permitted_roles){
for(i = 0; i < permitted_roles.length; i++){
if(message.member.roles.cache.has(permitted_roles[i])){
has_roles = true
}
}
if (!has_roles){
message.reply('You are not allowed to run this command!');
return;
}
}
if(permitted_channels){
msg_channel = message.channel;
channel_allowed = false
for(i = 0; i < permitted_channels.length; i++){
if(permitted_channels[i] == "dm" && msg_channel instanceof Discord.DMChannel){
channel_allowed = true;
break;
}else if(permitted_channels[i] == msg_channel.id){
channel_allowed = true;
break;
}
}
if(!channel_allowed){
return;
}
}
try {
command.execute(message);
} catch (error) {
console.error(error);
message.reply('There was an error trying to execute that command!');
}
});
client.login(token);

+ 1528
- 0
xi_music/package-lock.json
File diff suppressed because it is too large
View File


+ 22
- 0
xi_music/package.json View File

@ -0,0 +1,22 @@
{
"name": "xi_master",
"version": "1.0.0",
"description": "A master music bot for our xi network discord server",
"author": "Fringe <yigit@yigitcolakoglu.com>",
"main": "main.js",
"scripts": {
"start": "node main.js"
},
"dependencies": {
"@discordjs/opus": "^0.3.2",
"discord.js": "^12.0.2",
"ffmpeg": "0.0.4",
"ffmpeg-stream": "^0.6.0",
"fluent-ffmpeg": "^2.1.2",
"googleapis": "*",
"node-opus": "^0.3.3",
"prism-media": "github:hydrabolt/prism-media",
"sqlite3": "^5.0.0",
"ytdl-core": "^3.0.0"
}
}

+ 1
- 0
xi_news/.gitignore View File

@ -0,0 +1 @@
node_modules

+ 18
- 0
xi_news/Dockerfile View File

@ -0,0 +1,18 @@
FROM node:lts
RUN apt-get update || : && apt-get install python -y
RUN apt-get install ffmpeg -y
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
# If you are building your code for production
# # RUN npm ci --only=production
COPY . .
CMD [ "node", "main.js" ]

+ 16
- 0
xi_news/client.js View File

@ -0,0 +1,16 @@
const { Client, Collection } = require('discord.js');
module.exports = class extends Client {
constructor(config) {
super({
disableEveryone: true,
disabledEvents: ['TYPING_START'],
});
this.commands = new Collection();
this.queue = new Map();
this.config = config;
}
};

+ 16
- 0
xi_news/commands/crawler.js View File

@ -0,0 +1,16 @@
var
request = require('request'),
cheerio = require('cheerio');
function parse(url) {
request(url, function (error, response, body) {
var
$ = cheerio.load(body);
$('.question-summary .question-hyperlink').each(function () {
console.info($(this).text());
});
})
}
parse('http://stackoverflow.com/');

+ 36
- 0
xi_news/commands/get_rss.js View File

@ -0,0 +1,36 @@
const $ = require('jquery');
const request = require('request');
let Parser = require('rss-parser');
let parser = new Parser();
module.exports = {
name: 'get_rss',
description: 'Get rss feed',
async execute(message) {
let feed = await parser.parseURL('https://www.reddit.com/.rss');
console.log(feed.title);
feed.items[0](item => {
message.channel.send(
(item.title + ':' + item.link)
);
});
}
};

+ 278
- 0
xi_news/commands/jFeed-master/GPL-license.txt View File

@ -0,0 +1,278 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

+ 20
- 0
xi_news/commands/jFeed-master/MIT-license.txt View File

@ -0,0 +1,20 @@
Copyright (C) 2007 Jean-François Hovinne - http://www.hovinne.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 40
- 0
xi_news/commands/jFeed-master/Makefile View File

@ -0,0 +1,40 @@
SRC_DIR = src
BUILD_DIR = build
JS_FILES = ${SRC_DIR}/jfeed.js\
${SRC_DIR}/jfeeditem.js\
${SRC_DIR}/jatom.js\
${SRC_DIR}/jrss.js
WE = ${BUILD_DIR}/dist/jquery.jfeed.js
WE_PACK = ${BUILD_DIR}/dist/jquery.jfeed.pack.js
WE_ARCH = ../jquery.jfeed.tar.gz
MERGE = sed -s -e '1 s/^\xEF\xBB\xBF//' ${JS_FILES} > ${WE}
PACKER = perl -I${BUILD_DIR}/packer ${BUILD_DIR}/packer/jsPacker.pl -i ${WE} -o ${WE_PACK} -e62
all: archive
jfeed:
@@echo "Building" ${WE}
@@echo " - Merging files"
@@${MERGE}
@@echo ${WE} "Built"
@@echo
pack: jfeed
@@echo "Building" ${WE_PACK}
@@echo " - Compressing using Packer"
@@${PACKER}
@@echo ${WE_PACK} "Built"
@@echo
archive: pack
@@echo "Building" ${WE_ARCH}
@@echo " - Creating archive"
@@tar -C .. -czf ${WE_ARCH} --exclude '.git' jFeed

+ 47
- 0
xi_news/commands/jFeed-master/README.mediawiki View File

@ -0,0 +1,47 @@
'''jFeed: jQuery feed parser plugin'''
Copyright (C) 2007-2011 Jean-François Hovinne - http://hovinne.com/<br />
Dual licensed under the MIT (MIT-license.txt) and GPL (GPL-license.txt) licenses.
== Usage ==
<pre lang="javascript">jQuery.getFeed(options);</pre>
'''Options:'''
* <code>url</code>: the feed URL (required)
* <code>data</code>: data to be sent to the server. See [http://api.jquery.com/jQuery.ajax/ <code>jQuery.ajax</code>] data property
* <code>success</code>: a function to be called if the request succeeds. The function gets passed one argument: the <code>JFeed</code> object
'''Example:'''
<pre lang="javascript">
jQuery.getFeed({
url: 'rss.xml',
success: function(feed) {
alert(feed.title);
}
});
</pre>
== JFeed properties ==
* <code>feed.type</code>
* <code>feed.version</code>
* <code>feed.title</code>
* <code>feed.link</code>
* <code>feed.description</code>
* <code>feed.language</code>
* <code>feed.updated</code>
* <code>feed.items:</code> an array of JFeedItem
== JFeedItem properties ==
* <code>item.title</code>
* <code>item.link</code>
* <code>item.description</code>
* <code>item.updated</code>
* <code>item.id</code>
Please see the provided examples for more information.
A basic PHP proxy is also available (<code>proxy.php</code>), if you need to load external
feeds (for testing purposes only, do not use it on public websites).

+ 170
- 0
xi_news/commands/jFeed-master/build/dist/jquery.jfeed.js View File

@ -0,0 +1,170 @@
/* jFeed : jQuery feed parser plugin
* Copyright (C) 2007 Jean-François Hovinne - http://www.hovinne.com/
* Dual licensed under the MIT (MIT-license.txt)
* and GPL (GPL-license.txt) licenses.
*/
jQuery.getFeed = function(options) {
options = jQuery.extend({
url: null,
data: null,
cache: true,
success: null,
failure: null,
error: null,
global: true
}, options);
if (options.url) {
if (jQuery.isFunction(options.failure) && jQuery.type(options.error)==='null') {
// Handle legacy failure option
options.error = function(xhr, msg, e){
options.failure(msg, e);
}
} else if (jQuery.type(options.failure) === jQuery.type(options.error) === 'null') {
// Default error behavior if failure & error both unspecified
options.error = function(xhr, msg, e){
window.console&&console.log('getFeed failed to load feed', xhr, msg, e);
}
}
return $.ajax({
type: 'GET',
url: options.url,
data: options.data,
cache: options.cache,
dataType: (jQuery.browser.msie) ? "text" : "xml",
success: function(xml) {
var feed = new JFeed(xml);
if (jQuery.isFunction(options.success)) options.success(feed);
},
error: options.error,
global: options.global
});
}
};
function JFeed(xml) {
if (xml) this.parse(xml);
}
;
JFeed.prototype = {
type: '',
version: '',
title: '',
link: '',
description: '',
parse: function(xml) {
if (jQuery.browser.msie) {
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.loadXML(xml);
xml = xmlDoc;
}
if (jQuery('channel', xml).length == 1) {
this.type = 'rss';
var feedClass = new JRss(xml);
} else if (jQuery('feed', xml).length == 1) {
this.type = 'atom';
var feedClass = new JAtom(xml);
}
if (feedClass) jQuery.extend(this, feedClass);
}
};
function JFeedItem() {};
JFeedItem.prototype = {
title: '',
link: '',
description: '',
updated: '',
id: ''
};
function JAtom(xml) {
this._parse(xml);
};
JAtom.prototype = {
_parse: function(xml) {
var channel = jQuery('feed', xml).eq(0);
this.version = '1.0';
this.title = jQuery(channel).find('title:first').text();
this.link = jQuery(channel).find('link:first').attr('href');
this.description = jQuery(channel).find('subtitle:first').text();
this.language = jQuery(channel).attr('xml:lang');
this.updated = jQuery(channel).find('updated:first').text();
this.items = new Array();
var feed = this;
jQuery('entry', xml).each( function() {
var item = new JFeedItem();
item.title = jQuery(this).find('title').eq(0).text();
item.link = jQuery(this).find('link').eq(0).attr('href');
item.description = jQuery(this).find('content').eq(0).text();
item.updated = jQuery(this).find('updated').eq(0).text();
item.id = jQuery(this).find('id').eq(0).text();
feed.items.push(item);
});
}
};
function JRss(xml) {
this._parse(xml);
};
JRss.prototype = {
_parse: function(xml) {
if(jQuery('rss', xml).length == 0) this.version = '1.0';
else this.version = jQuery('rss', xml).eq(0).attr('version');
var channel = jQuery('channel', xml).eq(0);
this.title = jQuery(channel).find('title:first').text();
this.link = jQuery(channel).find('link:first').text();
this.description = jQuery(channel).find('description:first').text();
this.language = jQuery(channel).find('language:first').text();
this.updated = jQuery(channel).find('lastBuildDate:first').text();
this.items = new Array();
var feed = this;
jQuery('item', xml).each( function() {
var item = new JFeedItem();
item.title = jQuery(this).find('title').eq(0).text();
item.link = jQuery(this).find('link').eq(0).text();
item.description = jQuery(this).find('description').eq(0).text();
item.updated = jQuery(this).find('pubDate').eq(0).text();
item.id = jQuery(this).find('guid').eq(0).text();
feed.items.push(item);
});
}
};

+ 1
- 0
xi_news/commands/jFeed-master/build/dist/jquery.jfeed.pack.js View File

@ -0,0 +1 @@
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('2.W=b(7){7=2.R({y:o,L:o,K:Y,x:o,A:o,n:o,J:Y},7);g(7.y){g(2.V(7.A)&&2.m(7.n)===\'o\'){7.n=b(M,z,e){7.A(z,e)}}D g(2.m(7.A)===2.m(7.n)===\'o\'){7.n=b(M,z,e){1j.X&&X.1i(\'W 1h 1g 1f h\',M,z,e)}}1e $.1d({m:\'1c\',y:7.y,L:7.L,K:7.K,1b:(2.T.S)?"6":"4",x:b(4){f h=k I(4);g(2.V(7.x))7.x(h)},n:7.n,J:7.J})}};b I(4){g(4)3.U(4)};I.v={m:\'\',p:\'\',d:\'\',c:\'\',j:\'\',U:b(4){g(2.T.S){f H=k 1a("19.18");H.17(4);4=H}g(2(\'9\',4).E==1){3.m=\'C\';f w=k F(4)}D g(2(\'h\',4).E==1){3.m=\'16\';f w=k G(4)}g(w)2.R(3,w)}};b s(){};s.v={d:\'\',c:\'\',j:\'\',l:\'\',r:\'\'};b G(4){3.u(4)};G.v={u:b(4){f 9=2(\'h\',4).a(0);3.p=\'1.0\';3.d=2(9).5(\'d:i\').6();3.c=2(9).5(\'c:i\').t(\'Q\');3.j=2(9).5(\'15:i\').6();3.B=2(9).t(\'4:14\');3.l=2(9).5(\'l:i\').6();3.q=k P();f h=3;2(\'13\',4).O(b(){f 8=k s();8.d=2(3).5(\'d\').a(0).6();8.c=2(3).5(\'c\').a(0).t(\'Q\');8.j=2(3).5(\'12\').a(0).6();8.l=2(3).5(\'l\').a(0).6();8.r=2(3).5(\'r\').a(0).6();h.q.N(8)})}};b F(4){3.u(4)};F.v={u:b(4){g(2(\'C\',4).E==0)3.p=\'1.0\';D 3.p=2(\'C\',4).a(0).t(\'p\');f 9=2(\'9\',4).a(0);3.d=2(9).5(\'d:i\').6();3.c=2(9).5(\'c:i\').6();3.j=2(9).5(\'j:i\').6();3.B=2(9).5(\'B:i\').6();3.l=2(9).5(\'11:i\').6();3.q=k P();f h=3;2(\'8\',4).O(b(){f 8=k s();8.d=2(3).5(\'d\').a(0).6();8.c=2(3).5(\'c\').a(0).6();8.j=2(3).5(\'j\').a(0).6();8.l=2(3).5(\'10\').a(0).6();8.r=2(3).5(\'Z\').a(0).6();h.q.N(8)})}};',62,82,'||jQuery|this|xml|find|text|options|item|channel|eq|function|link|title||var|if|feed|first|description|new|updated|type|error|null|version|items|id|JFeedItem|attr|_parse|prototype|feedClass|success|url|msg|failure|language|rss|else|length|JRss|JAtom|xmlDoc|JFeed|global|cache|data|xhr|push|each|Array|href|extend|msie|browser|parse|isFunction|getFeed|console|true|guid|pubDate|lastBuildDate|content|entry|lang|subtitle|atom|loadXML|XMLDOM|Microsoft|ActiveXObject|dataType|GET|ajax|return|load|to|failed|log|window'.split('|')))

+ 467
- 0
xi_news/commands/jFeed-master/build/packer/Pack.pm View File

@ -0,0 +1,467 @@
#Pack (July 2005)
# Based on "Pack.js" by Dean Edwards <http://dean.edwards.name/>
# Ported to Perl by Rob Seiler, ELR Software Pty Ltd <http://www.elr.com.au>
# Copyright 2005. License <http://creativecommons.org/licenses/LGPL/2.1/>
package Pack;
use strict;
use Data::Dumper;
use ParseMaster;
# Package wide variable declarations
use vars qw/$VERSION $PM_VERSION
$_X_encodePrivate $_JSunpack $_JSdecode %baseLookup
$_X_encode10 $_X_encode36 $_X_encode62 $_X_encode95
$_JSencode10 $_JSencode36 $_JSencode62 $_JSencode95
@_X_parsers
$_X_script $_X_encoding $_X_fastDecode $_X_specialChars
/;
$VERSION = '024';
$PM_VERSION = $ParseMaster::VERSION;
# Package wide constants
my $X_IGNORE = q{$1};
my $X_ENCODE = q/\x24encode\(\x24count\)/; # NB: requires g modifier
my $PERL = 'perl'; # Flag to indicate whether we need to use one of our "internal" Perl encoding functions
my $JSCRIPT = 'jscript'; # or embed a pre-build JScript encoding function
########################################
##################
sub pack($$$$) { # require 4 arguments
##################
#print Dumper(@_);
($_X_script, $_X_encoding, $_X_fastDecode, $_X_specialChars) = @_;
# validate parameters (sort of!)
$_X_script .= "\n";
$_X_encoding = ($_X_encoding > 95) ? 95 : $_X_encoding;
@_X_parsers = (); # Reset parsers
####################
sub _X_pack($) { # require 1 argument
####################
# apply all parsing routines
my $X_script = shift;
for (my $i = 0; $i<scalar(@_X_parsers); $i++) {
my $X_parse = $_X_parsers[$i];
$X_script = &$X_parse($X_script);
}
return $X_script;
};
######################
sub _X_addParser { #
######################
# keep a list of parsing functions, they'll be executed all at once
my $X_parser = shift;
push (@_X_parsers,$X_parser);
}
#############################
sub _X_basicCompression { #
#############################
# zero encoding - just removal of white space and comments
my $X_script = shift;
my $parser = ParseMaster->new();
# make safe
$parser->escapeChar("\\");
# protect strings
$parser->add(q/'[^'\n\r]*'/, $X_IGNORE);
$parser->add(q/"[^"\n\r]*"/, $X_IGNORE);
# remove comments
$parser->add(q/\/\/[^\n\r]*[\n\r]/);
$parser->add(q/\/\*[^*]*\*+([^\/][^*]*\*+)*\//);
# protect regular expressions
$parser->add(q/\s+(\/[^\/\n\r\*][^\/\n\r]*\/g?i?)/, q{$2}); # IGNORE
$parser->add(q/[^\w\x24\/'"*)\?:]\/[^\/\n\r\*][^\/\n\r]*\/g?i?/, $X_IGNORE);
# remove: ;;; doSomething();
$parser->add(q/;;[^\n\r]+[\n\r]/) if ($_X_specialChars);
# remove redundant semi-colons
$parser->add(q/;+\s*([};])/, q{$2});
# remove white-space
$parser->add(q/(\b|\x24)\s+(\b|\x24)/, q{$2 $3});
$parser->add(q/([+\-])\s+([+\-])/, q{$2 $3});
$parser->add(q/\s+/, '');
# done
return $parser->exec($X_script);
}
###############################
sub _X_encodeSpecialChars { #
###############################
my $X_script = shift;
my $parser = ParseMaster->new();
# replace: $name -> n, $$name -> $$na
$parser->add(q/((\x24+)([a-zA-Z\x24_]+))(\d*)/,
sub {
my $X_offset = pop;
my @X_match = @_;
my $X_length = length($X_match[$X_offset+2]);
my $lengthnext = length($X_match[$X_offset+3]);
my $X_start = $X_length - ((($X_length - $lengthnext) > 0) ? ($X_length - $lengthnext) : 0);
my $str = $X_match[$X_offset+1];
$str = substr($str,$X_start,$X_length) . $X_match[$X_offset+4];
return "$str";
});
# replace: _name -> _0, double-underscore (__name) is ignored
my $X_regexp = q/\b_[A-Za-z\d]\w*/;
# build the word list
my %X_keywords = &_X_analyze($X_script, $X_regexp, $_X_encodePrivate);
#print Dumper(%X_keywords);
# quick ref
my $X_encoded = \$X_keywords{X_encoded}; # eg _private1 => '_0',_private2 => '_1';
#print Dumper($X_encoded);
$parser->add($X_regexp, sub {my $X_offset = pop; my @X_match = @_; return ${$X_encoded}->{$X_match[$X_offset]};});
return $parser->exec($X_script);
};
###########################
sub _X_encodeKeywords { #
###########################
my $X_script = shift;
# escape high-ascii values already in the script (i.e. in strings)
if ($_X_encoding > 62) {$X_script = &_X_escape95($X_script)};
# create the parser
my $parser = ParseMaster->new();
my $X_encode = &_X_getEncoder($_X_encoding,$PERL);
# for high-ascii, don't encode single character low-ascii
my $X_regexp = ($_X_encoding > 62) ? q/\w\w+/ : q/\w+/;
# build the word list
my %X_keywords = &_X_analyze($X_script, $X_regexp, $X_encode);
#print Dumper(%X_keywords);
my $X_encoded = \$X_keywords{X_encoded}; # eg alert => 2, function => 10 etc
# encode
$parser->add($X_regexp, sub {my $X_offset = pop; my @X_match = @_; return ${$X_encoded}->{$X_match[$X_offset]};});
# if encoded, wrap the script in a decoding function
return $X_script && _X_bootStrap(\$parser->exec($X_script), \%X_keywords);
}
####################
sub _X_analyze { #
####################
#print Dumper(@_);
my ($X_script, $X_regexp, $X_encode) = @_;
# analyse
# retreive all words in the script
my @X_all = $X_script =~ m/$X_regexp/g; # Save all captures in a list context
my %XX_sorted = (); # list of words sorted by frequency
my %XX_encoded = (); # dictionary of word->encoding
my %XX_protected = (); # instances of "protected" words
if (@X_all) {
my @X_unsorted = (); # same list, not sorted
my %X_protected = (); # "protected" words (dictionary of word->"word")
my %X_values = (); # dictionary of charCode->encoding (eg. 256->ff)
my %X_count = (); # word->count
my $i = scalar(@X_all); my $j = 0; my $X_word = '';
# count the occurrences - used for sorting later
do {
$X_word = '$' . $X_all[--$i];
if (!exists($X_count{$X_word})) {
$X_count{$X_word} = [0,$i]; # Store both the usage count and original array position (ie a secondary sort key)
$X_unsorted[$j] = $X_word;
# make a dictionary of all of the protected words in this script
# these are words that might be mistaken for encoding
$X_values{$j} = &$X_encode($j);
my $v = '$'.$X_values{$j};
$X_protected{$v} = $j++;
}
# increment the word counter
$X_count{$X_word}[0]++;
} while ($i);
#print Dumper (%X_values);
#print Dumper (@X_unsorted);
#print Dumper (%X_protected);
# prepare to sort the word list, first we must protect
# words that are also used as codes. we assign them a code
# equivalent to the word itself.
# e.g. if "do" falls within our encoding range
# then we store keywords["do"] = "do";
# this avoids problems when decoding
$i = scalar(@X_unsorted);
do {
$X_word = $X_unsorted[--$i];
if (exists($X_protected{$X_word})) {
$XX_sorted{$X_protected{$X_word}} = substr($X_word,1);
$XX_protected{$X_protected{$X_word}} = 1; # true
$X_count{$X_word}[0] = 0;
}
} while ($i);
#print Dumper (%XX_protected);
#print Dumper (%XX_sorted);
#print Dumper (%X_count);
# sort the words by frequency
# Sort with count a primary key and original array order as secondary key - which is apparently the default in javascript!
@X_unsorted = sort ({($X_count{$b}[0] - $X_count{$a}[0]) or ($X_count{$b}[1] <=> $X_count{$a}[1])} @X_unsorted);
#print Dumper (@X_unsorted) . "\n";
$j = 0;
# because there are "protected" words in the list
# we must add the sorted words around them
do {
if (!exists($XX_sorted{$i})) {$XX_sorted{$i} = substr($X_unsorted[$j++],1)}
$XX_encoded{$XX_sorted{$i}} = $X_values{$i};
} while (++$i < scalar(@X_unsorted));
}
#print Dumper(X_sorted => \%XX_sorted, X_encoded => \%XX_encoded, X_protected => \%XX_protected);
return (X_sorted => \%XX_sorted, X_encoded => \%XX_encoded, X_protected => \%XX_protected);
}
######################
sub _X_bootStrap { #
######################
# build the boot function used for loading and decoding
my ($X_packed, $X_keywords) = @_; # Reference arguments!
#print Dumper ($X_keywords) . "\n";
# $packed: the packed script - dereference and escape
$X_packed = "'" . &_X_escape($$X_packed) ."'";
my %sorted = %{$$X_keywords{X_sorted}}; # Dereference to local variables
my %protected = %{$$X_keywords{X_protected}}; # for simplicity
my @sorted = ();
foreach my $key (keys %sorted) {$sorted[$key] = $sorted{$key}}; # Convert hash to a standard list
# ascii: base for encoding
my $X_ascii = ((scalar(@sorted) > $_X_encoding) ? $_X_encoding : scalar(@sorted)) || 1;
# count: number of (unique {RS}) words contained in the script
my $X_count = scalar(@sorted); # Use $X_count for assigning $X_ascii
# keywords: list of words contained in the script
foreach my $i (keys %protected) {$sorted[$i] = ''}; # Blank out protected words
#print Dumper(@sorted) . "\n";
# convert from a string to an array - prepare keywords as a JScript string->array {RS}
$X_keywords = "'" . join('|',@sorted) . "'.split('|')";
# encode: encoding function (used for decoding the script)
my $X_encode = $_X_encoding > 62 ? $_JSencode95 : &_X_getEncoder($X_ascii,$JSCRIPT); # This is a JScript function (as a string)
$X_encode =~ s/_encoding/\x24ascii/g; $X_encode =~ s/arguments\.callee/\x24encode/g;
my $X_inline = '$count' . ($X_ascii > 10 ? '.toString($ascii)' : '');
# decode: code snippet to speed up decoding
my $X_decode = '';
if ($_X_fastDecode) {
# create the decoder
$X_decode = &_X_getFunctionBody($_JSdecode); # ie from the Javascript literal function
if ($_X_encoding > 62) {$X_decode =~ s/\\\\w/[\\xa1-\\xff]/g}
# perform the encoding inline for lower ascii values
elsif ($X_ascii < 36) {$X_decode =~ s/$X_ENCODE/$X_inline/g}
# special case: when $X_count==0 there ar no keywords. i want to keep
# the basic shape of the unpacking funcion so i'll frig the code...
if (!$X_count) {$X_decode =~ s/(\x24count)\s*=\s*1/$1=0/}
}
# boot function
my $X_unpack = $_JSunpack;
if ($_X_fastDecode) {
# insert the decoder
$X_unpack =~ s/\{/\{$X_decode;/;
}
$X_unpack =~ s/"/'/g;
if ($_X_encoding > 62) { # high-ascii
# get rid of the word-boundaries for regexp matches
$X_unpack =~ s/'\\\\b'\s*\+|\+\s*'\\\\b'//g; # Not checked! {RS}
}
if ($X_ascii > 36 || $_X_encoding > 62 || $_X_fastDecode) {
# insert the encode function
$X_unpack =~ s/\{/\{\$encode=$X_encode;/;
} else {
# perform the encoding inline
$X_unpack =~ s/$X_ENCODE/$X_inline/;
}
# arguments {RS} Do this before using &pack because &pack changes the pack parameters (eg $fastDecode) in Perl!!
my $X_params = "$X_packed,$X_ascii,$X_count,$X_keywords"; # Interpolate to comma separated string
if ($_X_fastDecode) {
# insert placeholders for the decoder
$X_params .= ',0,{}';
}
# pack the boot function too
$X_unpack = &pack($X_unpack,0,0,1);
# the whole thing
return "eval(" . $X_unpack . "(" . $X_params . "))\n";
};
#######################
sub _X_getEncoder { #
#######################
# mmm.. ..which one do i need ?? ({RS} Perl or JScript ??)
my ($X_ascii,$language) = @_;
my $perl_encoder = ($X_ascii > 10) ? ($X_ascii > 36) ? ($X_ascii > 62) ? $_X_encode95 : $_X_encode62 : $_X_encode36 : $_X_encode10;
my $jscript_encoder = ($X_ascii > 10) ? ($X_ascii > 36) ? ($X_ascii > 62) ? $_JSencode95 : $_JSencode62 : $_JSencode36 : $_JSencode10;
return ($language eq $JSCRIPT) ? $jscript_encoder : $perl_encoder;
};
#############################
# Perl versions of encoders #
#############################
# base10 zero encoding - characters: 0123456789
$_X_encode10 = sub {return &_encodeBase(shift,10)};
# base36 - characters: 0123456789abcdefghijklmnopqrstuvwxyz
$_X_encode36 = sub {return &_encodeBase(shift,36)};
# base62 - characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
$_X_encode62 = sub {return &_encodeBase(shift,62)};
# high-ascii values - characters: 、�ウЖ��⑭�渦慨偽係杭纂従神疎団兎波品北洋椀冫嘖孛忤掣桀毳烙痰邃繙艾蜉謖邇關髓齡��巐鄕�
$_X_encode95 = sub {return &_encodeBase(shift,95)};
# Lookup character sets for baseN encoding
$baseLookup{10} = [(0..9)[0..9]]; # base 10
$baseLookup{36} = [(0..9,'a'..'z')[0..35]]; # base 36
$baseLookup{62} = [(0..9,'a'..'z','A'..'Z')[0..61]]; # base 62
$baseLookup{95} = (); for (my $i=0; $i<95; $i++) {$baseLookup{95}[$i] = chr($i+161)}; # base95 (high ascii)
#print Dumper(%baseLookup);
#####################
sub _encodeBase { #
#####################
# Generic base conversion function using defined lookup arrays (perl version only)
my ($X_charCode, $base) = @_;
my $X_encoded = '';
# Do we know this encoding?
if (exists ($baseLookup{$base})) {
if ($X_charCode == 0) {$X_encoded = $baseLookup{$base}[0]}
while($X_charCode > 0) {
$X_encoded = $baseLookup{$base}[$X_charCode % $base] . $X_encoded;
$X_charCode = int($X_charCode / $base);
}
}
else {$X_encoded = "$X_charCode"} # default is to return unchanged (ie as for base 10) if no baselookup is available
return $X_encoded;
};
#############################
$_X_encodePrivate = sub { #
#############################
# special _chars
my $X_charCode = shift;
return '_' . $X_charCode;
};
############################
sub _X_escape($script) { #
############################
# protect characters used by the parser
my $X_script = shift;
$X_script =~ s/([\\'])/\\$1/g;
return $X_script;
};
#####################
sub _X_escape95 { #
#####################
# protect high-ascii characters already in the script
my $X_script = shift;
$X_script =~ s/([\xa1-\xff])/sprintf("\\x%1x",ord($1))/eg;
return $X_script;
};
############################
sub _X_getFunctionBody { #
############################
# extract the body of a function (ie between opening/closing {}) - consistent with Dean Edwards approach
my $X_function = shift;
$X_function =~ m/^.*\{(.*)\}*$/sg; # Multiline, global (greedy)
my $start = index($X_function,'{');
my $end = rindex($X_function,'}');
$X_function = substr($X_function,($start+1),($end-1-$start));
return $X_function;
};
######################
sub _X_globalize { #
######################
# set the global flag on a RegExp (you have to create a new one) !!! Unused in perl version
# my $X_regexp = shift;
};
# build the parsing routine
&_X_addParser(\&_X_basicCompression);
&_X_addParser(\&_X_encodeSpecialChars) if ($_X_specialChars);
&_X_addParser(\&_X_encodeKeywords) if ($_X_encoding);
# go!
return &_X_pack($_X_script);
}
########################
# Javascript Literals #
########################
# JScript function "_unpack" - from DeanEdwards pack.js (NB: No ";" after final "}")
($_JSunpack) = <<'END_JSCRIPT_UNPACK';
/* unpacking function - this is the boot strap function */
/* data extracted from this packing routine is passed to */
/* this function when decoded in the target */
function($packed, $ascii, $count, $keywords, $encode, $decode) {
while ($count--)
if ($keywords[$count])
$packed = $packed.replace(new RegExp('\\b' + $encode($count) + '\\b', 'g'), $keywords[$count]);
/* RS_Debug = $packed; */ /* {RS} !!!!!!!!! */
return $packed;
}
END_JSCRIPT_UNPACK
# JScript function "_decode" - from DeanEdwards pack.js
($_JSdecode) = <<'END_JSCRIPT_DECODE';
/* code-snippet inserted into the unpacker to speed up decoding */
function() {
/* does the browser support String.replace where the */
/* replacement value is a function? */
if (!''.replace(/^/, String)) {
/* decode all the values we need */
while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count);
/* global replacement function */
$keywords = [function($encoded){return $decode[$encoded]}];
/* generic match */
$encode = function(){return'\\w+'};
/* reset the loop counter - we are now doing a global replace */
$count = 1;
}
};
END_JSCRIPT_DECODE
# JScript versions of encoders
($_JSencode10) = <<'END_JSCRIPT_ENCODE10';
/* zero encoding */
/* characters: 0123456789 */
function($charCode) {
return $charCode;
};
END_JSCRIPT_ENCODE10
($_JSencode36) = <<'END_JSCRIPT_ENCODE36';
/* inherent base36 support */
/* characters: 0123456789abcdefghijklmnopqrstuvwxyz */
function($charCode) {
return $charCode.toString(36);
};
END_JSCRIPT_ENCODE36
($_JSencode62) = <<'END_JSCRIPT_ENCODE62';
/* hitch a ride on base36 and add the upper case alpha characters */
/* characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ */
function($charCode) {
return ($charCode < _encoding ? '' : arguments.callee(parseInt($charCode / _encoding))) +
(($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36));
};
END_JSCRIPT_ENCODE62
($_JSencode95) = <<'END_JSCRIPT_ENCODE95';
/* use high-ascii values */
/* characters: 、�ウЖ��⑭�渦慨偽係杭纂従神疎団兎波品北洋椀冫嘖孛忤掣桀毳烙痰邃繙艾蜉謖邇關髓齡��巐鄕� */
function($charCode) {
return ($charCode < _encoding ? '' : arguments.callee($charCode / _encoding)) +
String.fromCharCode($charCode % _encoding + 161);
};
END_JSCRIPT_ENCODE95
###########
# END #
###########
1; # Pack #
###########

+ 207
- 0
xi_news/commands/jFeed-master/build/packer/ParseMaster.pm View File

@ -0,0 +1,207 @@
#ParseMaster (July 25 2005)
# Based on "ParseMaster.js" by Dean Edwards <http://dean.edwards.name/>
# Ported to Perl by Rob Seiler, ELR Software Pty Ltd <http://www.elr.com.au>
# Copyright 2005. License <http://creativecommons.org/licenses/LGPL/2.1/>
package ParseMaster;
use strict;
use Data::Dumper;
# Package wide variable declarations
use vars qw/$VERSION
@_X_escaped @_X_patterns
/;
$VERSION = '017';
# constants
my $X_EXPRESSION = 0;
my $X_REPLACEMENT = 1;
my $X_LENGTH = 2;
# re's used to determine nesting levels
my $X_GROUPS = qr/\(/o; # NB: Requires g modifier!
my $X_SUB_REPLACE = qr/\$\d/o;
my $X_INDEXED = qr/^\$\d+$/o;
my $XX_ESCAPE = qr/\\./o; # NB: Requires g modifier!
my $XX_DELETED = qr/\001[^\001]*\001/o; # NB: Requires g modifier!
my $DIGIT = qr/[^\D]/o; # Yep - this is a digit - contains no non-digits
# Constructor
sub new {
my $class = shift;
my $self = {};
@_X_escaped = (); # Re-initialize global for each instance
@_X_patterns = (); # Re-initialize global for each instance
# Instance variables - access by similarly named set/get functions
$self->{_ignoreCase_} = 0;
$self->{_escapeChar_} = '';
bless ($self, $class);
return $self;
}
sub ignoreCase {
my ($self, $value) = @_;
if (defined($value)) {
$self->{_ignoreCase_} = $value;
}
return $self->{_ignoreCase_};
}
sub escapeChar{
my ($self, $value) = @_;
if (defined($value)) {
$self->{_escapeChar_} = $value;
}
return $self->{_escapeChar_};
}
#######################
# Public Parsemaster functions
my $X_DELETE = sub(@$) {
my $X_offset = pop;
my @X_match = @_;
return (chr(001) . $X_match[$X_offset] . chr(001));
}; # NB semicolon required for closure!
# create and add a new pattern to the patterns collection
sub add {
my ($self, $expression, $X_replacement) = @_;
if (!$X_replacement) {$X_replacement = $X_DELETE};
# count the number of sub-expressions
my $temp = &_X_internalEscape($expression);
my $length = 1; # Always at least one because each pattern is itself a sub-expression
$length += $temp =~ s/$X_GROUPS//g; # One way to count the left capturing parentheses in the regexp string
# does the pattern deal with sub-expressions?
if ((ref($X_replacement) ne "CODE") && ($X_replacement =~ m/$X_SUB_REPLACE/)) {
if ($X_replacement =~ m/$X_INDEXED/) { # a simple lookup? (eg "$2")
# store the index (used for fast retrieval of matched strings)
$X_replacement = substr($X_replacement,1) - 1;
}
else { # a complicated lookup (eg "Hello $2 $1")
my $i = $length;
while ($i) { # Had difficulty getting Perl to do Dean's splitting and joining of strings containing $'s
my $str = '$a[$o+' . ($i-1) . ']'; # eg $a[$o+1]
$X_replacement =~ s/\$$i/$str/; # eg $2 $3 -> $a[$o+1] $a[$o+2]
$i--;
}
# build a function to do the lookup - returns interpolated string of array lookups
$X_replacement = eval('sub {my $o=pop; my @a=@_; return "' . $X_replacement . '"};');
}
}
else {}
# pass the modified arguments
&_X_add($expression || q/^$/, $X_replacement, $length);
}
# execute the global replacement
sub exec {
#print Dumper(@_X_patterns);
my ($self, $X_string) = @_;
my $escChar = $self->escapeChar();
my $ignoreCase = $self->ignoreCase();
my ($regexp,$captures) = &_getPatterns(); # Concatenated and parenthesized regexp eg '(regex1)|(regex2)|(regex3)' etc
$X_string = &_X_escape($X_string, $escChar);
if ($ignoreCase) {$X_string =~ s/$regexp/{&_X_replacement(&_matchVars($captures,\$X_string))}/gie} # Pass $X_String as a
else {$X_string =~ s/$regexp/{&_X_replacement(&_matchVars($captures,\$X_string))}/ge} # reference for speed
$X_string = &_X_unescape($X_string, $escChar);
$X_string =~ s/$XX_DELETED//g;
return $X_string;
}
sub _X_add {
push (@_X_patterns, [@_]); # Save each argument set as is into an array of arrays
}
# this is the global replace function (it's quite complicated)
sub _X_replacement {
my (@arguments) = @_;
#print Dumper (@arguments);
if ($arguments[0] le '') {return ''}
# Dereference last index (source String) here - faster than in _matchVars (maybe not needed at all?)
$arguments[$#arguments] = ${$arguments[$#arguments]};
my $i = 1;
# loop through the patterns
for (my $j=0; $j<scalar(@_X_patterns); $j++) { # Loop through global all @_X_patterns
my @X_pattern = @{$_X_patterns[$j]};
# do we have a result? NB: "if ($arguments[$i])" as in Dean's Javascript is false for the value 0!!!
if ((defined $arguments[$i]) && ($arguments[$i] gt '')) {
my $X_replacement = $X_pattern[$X_REPLACEMENT];
# switch on type of $replacement
if (ref($X_replacement) eq "CODE") { # function
return &$X_replacement(@arguments,$i);
}
elsif ($X_replacement =~ m/$DIGIT/) { # number (contains no non-digits)
return $arguments[$X_replacement + $i];
}
else { # default
return $X_replacement; # default
}
} # skip over references to sub-expressions
else {$i += $X_pattern[$X_LENGTH]}
}
}
#######################
# Private functions
#######################
# encode escaped characters
sub _X_escape {
my ($X_string, $X_escapeChar) = @_;
if ($X_escapeChar) {
my $re = '\\'.$X_escapeChar.'(.)';
$X_string =~ s/$re/{push(@_X_escaped,$1); $X_escapeChar}/ge;
}
return $X_string;
}
# decode escaped characters
sub _X_unescape {
my ($X_string, $X_escapeChar) = @_;
if ($X_escapeChar) { # We'll only do this if there is an $X_escapeChar!
my $re = '\\'.$X_escapeChar;
$X_string =~ s/$re/{$X_escapeChar . (shift(@_X_escaped))}/ge; # Don't use Dean Edwards as below 'or' here - because zero will return ''!
# $X_string =~ s/$re/{$X_escapeChar . (shift(@_X_escaped) || '')}/ge;
}
return $X_string;
}
sub _X_internalEscape {
my ($string) = shift;
$string =~ s/$XX_ESCAPE//g;
return $string;
}
# Builds an array of match variables to (approximately) emulate that available in Javascript String.replace()
sub _matchVars {
my ($m,$sref) = @_;
my @args = (1..$m); # establish the number potential memory variables
my @mv = map {eval("\$$_")} @args; # matchvarv[1..m] = the memory variables $1 .. $m
unshift (@mv, $&); # matchvar[0] = the substring that matched
push (@mv, length($`)); # matchvar[m+1] = offset within the source string where the match occurred (= length of prematch string)
push (@mv, $sref); # matchvar[m+2] = reference to full source string (dereference in caller if/when needed)
#print Dumper (@mv);
return @mv;
}
sub _getPatterns {
my @Patterns = ();
my $lcp = 0;
for (my $i=0; $i<scalar(@_X_patterns); $i++) { # Loop through global all @_patterns
push (@Patterns, $_X_patterns[$i][$X_EXPRESSION]); # accumulate the expressions
$lcp += $_X_patterns[$i][$X_LENGTH]; # sum the left capturing parenthesis counts
}
my $str = "(" . join(')|(',@Patterns). ")"; # enclose each pattern in () separated by "|"
return ($str, $lcp);
}
##################
# END #
##################
1; # ParseMaster #
##################

+ 163
- 0
xi_news/commands/jFeed-master/build/packer/jsPacker.pl View File

@ -0,0 +1,163 @@
#!perl
#jsPacker (July 2005)
#
use strict;
use Pack;
use vars qw($PROGNAME $VERSION
$opt_h $opt_q $opt_v $opt_i $opt_o $opt_e $opt_f $opt_s);
use Getopt::Std;
$PROGNAME = $0;
$VERSION = '1.00b';
my $Description = 'A JavaScript Compressor/Obfuscator';
my $Version = "v$VERSION\[p$Pack::VERSION-pm$Pack::PM_VERSION\]";
# "English" versions of settings
my %ENCODINGS = (0=>'None', 10=>'Decimal', 36=>'Normal', 62=>'Normal', 95=>'High-ascii');
my %SETTINGS = (0=>'No', 1=>'Yes');
exit(0) if &main();
exit(1);
################
# Sub-routines #
################
# Main program
sub main {
# Get command line options
&getopts('hqvfsi:o:e:');
$opt_h ||= 0; # $opt_h shows usage and exits
$opt_q ||= 0; # $opt_q sets quiet mode (no stdout output)
$opt_v ||= 0; # $opt_v shows version and exits
$opt_i ||= ''; # $opt_i is input file. Required!
$opt_o ||= ''; # $opt_o is output file. If not set, use standard output
$opt_e ||= 0; # $opt_e encoding level (0,10,36,62,95)
$opt_f ||= 0; # $opt_f use fast decoding
$opt_s ||= 0; # $opt_x use special characters
# Display help or version if requested
if ($opt_h) {&usage("help")}
if ($opt_v) {&usage("version")}
# Constrain encoding level, fastdecoding and specialcharacters to allowed limits
$opt_e = ($opt_e > 0) ? ($opt_e > 10) ? ($opt_e > 36) ? ($opt_e > 62) ? 95 : 62 : 36 : 10 : 0;
$opt_f = ($opt_f) ? 1 : 0;
$opt_s = ($opt_s) ? 1 : 0;
# Do the job if an input file is specified
if ($opt_i) {
# Read the source script
my $script = &readInputFile($opt_i);
# Pack the source script
my $packedscript = &Pack::pack($script,$opt_e, $opt_f, $opt_s);
# Show what happened (if not in quiet mode)
if (!$opt_q) {showJobDetails($opt_i, $opt_o, $opt_e, $opt_f,$opt_s,\$script,\$packedscript)}
# Output the packed script
if ($opt_o) {&writeOutputFile($opt_o,\$packedscript)} # to output file if specifed
else {print "$packedscript"} # otherwise to STDOUT
}
else { # If no input file is specified, display help
&usage();
}
return(1);
}
######################
sub showJobDetails { #
######################
# Show details of input/output files, settings and compression ratio
my ($inputfile, $outputfile,
$encoding, $fastdecode, $specialchars,
$instringref, $outstringref) = @_;
print "$PROGNAME $Version\n";
print "\tSource file : ";
print "\"$inputfile\"\n";
print (($outputfile) ? ("\tOutput file : \"$outputfile\"\n") : ''); # Print only if output is going to a file
print "\tSettings : encoding=$ENCODINGS{$encoding} fastdecode=$SETTINGS{$fastdecode} specialchars=$SETTINGS{$specialchars}\n";
print "\tCompression : " . &compressionRatio($instringref, $outstringref). "\n\n";
}
#####################
sub readInputFile { #
#####################
# Read content (source script) from input file
my $filename = shift;
open(FH, $filename) || die "Error!!! Problem opening input file \"$filename\"!\n";
my @content = <FH>;
close(FH);
return join('',@content);
}
#######################
sub writeOutputFile { #
#######################
# Write content (packed script) to output file
my ($filename,$refcontent) = @_;
open(FH, ">$filename") || die "Error!!! Problem opening output file \"$filename\"\n";
print(FH $$refcontent);
close(FH);
}
########################
sub compressionRatio { #
########################
# Calculate the ratio of output string to input string
my ($sref1,$sref2) = @_;
my $ratio = (length($$sref2) / (length($$sref1)||1));
$ratio = sprintf "%.2f", $ratio;
return $ratio;
}
#############
sub usage { #
#############
# Inform user about usage, version and exit
my $showusage = 0;
my $showversion = 0;
my $params = shift;
if (defined $params) {
if ($params eq "help") {$showusage = 1;}
elsif ($params eq "version") {$showversion = 1;}
else {$showusage = 1;}
}
else {$showversion = 1;}
if ($showversion) {
print<<EOT;
$PROGNAME $Version
$Description
\tBased on "Packer.js" by Dean Edwards <http://dean.edwards.name/>
\tPorted to Perl by Rob Seiler, ELR Software Pty Ltd <http://www.elr.com.au>
\tCopyright 2005. License <http://creativecommons.org/licenses/LGPL/2.1/>
Use "$PROGNAME -h" for options
EOT
exit(1);
}
if ($showusage) {
print<<EOT;
$PROGNAME $Version
$Description
Usage:
\t$PROGNAME -i inputfile [-o outputfile] [-eX] [-f] [-s] [-qvh]\n
\t-i <inputfile> (eg -i myscript.js)
\t-o <outputfile> (eg -o myscript-p.js)
\t-eN <encoding> [0=None 10=Numeric 62=Normal(alphanumeric) 95=High-ascii]
\t-f <fast decode>
\t-s <special characters>
\t-q quiet mode
\t-v version
\t-h help
Examples:
\t$PROGNAME -i myscript.js
\t$PROGNAME -i myscript.js -o packed.js
\t$PROGNAME -i myscript.js -o packed.js -e10 -f -s
\t$PROGNAME -i myscript.js -e95 -fsq > packed.js
EOT
exit(1);
}
}

+ 65
- 0
xi_news/commands/jFeed-master/example-proxy.html View File

@ -0,0 +1,65 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jFeed - jQuery feed parser plugin - example</title>
<style type="text/css">
h3 { margin-bottom: 5px; }
div.updated { color: #999; margin-bottom: 5px; font-size: 0.8em; }
</style>
<script type="text/javascript" src="jquery/jquery.js"></script>
<script type="text/javascript" src="build/dist/jquery.jfeed.pack.js"></script>
<script type="text/javascript">
jQuery(function() {
jQuery.getFeed({
url: 'proxy.php?url=http://www.hovinne.com/feed/',
success: function(feed) {
jQuery('#result').append('<h2>'
+ '<a href="'
+ feed.link
+ '">'
+ feed.title
+ '</a>'
+ '</h2>');
var html = '';
for(var i = 0; i < feed.items.length && i < 5; i++) {
var item = feed.items[i];
html += '<h3>'
+ '<a href="'
+ item.link
+ '">'
+ item.title
+ '</a>'
+ '</h3>';
html += '<div class="updated">'
+ item.updated
+ '</div>';
html += '<div>'
+ item.description
+ '</div>';
}
jQuery('#result').append(html);
}
});
});
</script>
</head>
<body>
<h1>jFeed - jQuery feed parser plugin - example</h1>
<div id="result" />
</body>
</html>

+ 65
- 0
xi_news/commands/jFeed-master/example.html View File

@ -0,0 +1,65 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jFeed - jQuery feed parser plugin - example</title>
<style type="text/css">
h3 { margin-bottom: 5px; }
div.updated { color: #999; margin-bottom: 5px; font-size: 0.8em; }
</style>
<script type="text/javascript" src="jquery/jquery.js"></script>
<script type="text/javascript" src="build/dist/jquery.jfeed.pack.js"></script>
<script type="text/javascript">
jQuery(function() {
jQuery.getFeed({
url: 'xml/rss-20.xml',
success: function(feed) {
jQuery('#result').append('<h2>'
+ '<a href="'
+ feed.link
+ '">'
+ feed.title
+ '</a>'
+ '</h2>');
var html = '';
for(var i = 0; i < feed.items.length && i < 5; i++) {
var item = feed.items[i];
html += '<h3>'
+ '<a href="'
+ item.link
+ '">'
+ item.title
+ '</a>'
+ '</h3>';
html += '<div class="updated">'
+ item.updated
+ '</div>';
html += '<div>'
+ item.description
+ '</div>';
}
jQuery('#result').append(html);
}
});
});
</script>
</head>
<body>
<h1>jFeed - jQuery feed parser plugin - example</h1>
<div id="result" />
</body>
</html>

+ 4
- 0
xi_news/commands/jFeed-master/jquery/jquery.js
File diff suppressed because it is too large
View File


+ 12
- 0
xi_news/commands/jFeed-master/proxy.php View File

@ -0,0 +1,12 @@
<?php
header('Content-type: application/xml');
$handle = fopen($_REQUEST['url'], "r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
echo $buffer;
}
fclose($handle);
}
?>

+ 36
- 0
xi_news/commands/jFeed-master/src/jatom.js View File

@ -0,0 +1,36 @@
function JAtom(xml) {
this._parse(xml);
};
JAtom.prototype = {
_parse: function(xml) {
var channel = jQuery('feed', xml).eq(0);
this.version = '1.0';
this.title = jQuery(channel).find('title:first').text();
this.link = jQuery(channel).find('link:first').attr('href');
this.description = jQuery(channel).find('subtitle:first').text();
this.language = jQuery(channel).attr('xml:lang');
this.updated = jQuery(channel).find('updated:first').text();
this.items = new Array();
var feed = this;
jQuery('entry', xml).each( function() {
var item = new JFeedItem();
item.title = jQuery(this).find('title').eq(0).text();
item.link = jQuery(this).find('link').eq(0).attr('href');
item.description = jQuery(this).find('content').eq(0).text();
item.updated = jQuery(this).find('updated').eq(0).text();
item.id = jQuery(this).find('id').eq(0).text();
feed.items.push(item);
});
}
};

+ 85
- 0
xi_news/commands/jFeed-master/src/jfeed.js View File

@ -0,0 +1,85 @@
/* jFeed : jQuery feed parser plugin
* Copyright (C) 2007 Jean-François Hovinne - http://www.hovinne.com/
* Dual licensed under the MIT (MIT-license.txt)
* and GPL (GPL-license.txt) licenses.
*/
jQuery.getFeed = function(options) {
options = jQuery.extend({
url: null,
data: null,
cache: true,
success: null,
failure: null,
error: null,
global: true
}, options);
if (options.url) {
if (jQuery.isFunction(options.failure) && jQuery.type(options.error)==='null') {
// Handle legacy failure option
options.error = function(xhr, msg, e){
options.failure(msg, e);
}
} else if (jQuery.type(options.failure) === jQuery.type(options.error) === 'null') {
// Default error behavior if failure & error both unspecified
options.error = function(xhr, msg, e){
window.console&&console.log('getFeed failed to load feed', xhr, msg, e);
}
}
return $.ajax({
type: 'GET',
url: options.url,
data: options.data,
cache: options.cache,
dataType: (jQuery.browser.msie) ? "text" : "xml",
success: function(xml) {
var feed = new JFeed(xml);
if (jQuery.isFunction(options.success)) options.success(feed);
},
error: options.error,
global: options.global
});
}
};
function JFeed(xml) {
if (xml) this.parse(xml);
}
;
JFeed.prototype = {
type: '',
version: '',
title: '',
link: '',
description: '',
parse: function(xml) {
if (jQuery.browser.msie) {
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.loadXML(xml);
xml = xmlDoc;
}
if (jQuery('channel', xml).length == 1) {
this.type = 'rss';
var feedClass = new JRss(xml);
} else if (jQuery('feed', xml).length == 1) {
this.type = 'atom';
var feedClass = new JAtom(xml);
}
if (feedClass) jQuery.extend(this, feedClass);
}
};

+ 11
- 0
xi_news/commands/jFeed-master/src/jfeeditem.js View File

@ -0,0 +1,11 @@
function JFeedItem() {};
JFeedItem.prototype = {
title: '',
link: '',
description: '',
updated: '',
id: ''
};

+ 38
- 0
xi_news/commands/jFeed-master/src/jrss.js View File

@ -0,0 +1,38 @@
function JRss(xml) {
this._parse(xml);
};
JRss.prototype = {
_parse: function(xml) {
if(jQuery('rss', xml).length == 0) this.version = '1.0';
else this.version = jQuery('rss', xml).eq(0).attr('version');
var channel = jQuery('channel', xml).eq(0);
this.title = jQuery(channel).find('title:first').text();
this.link = jQuery(channel).find('link:first').text();
this.description = jQuery(channel).find('description:first').text();
this.language = jQuery(channel).find('language:first').text();
this.updated = jQuery(channel).find('lastBuildDate:first').text();
this.items = new Array();
var feed = this;
jQuery('item', xml).each( function() {
var item = new JFeedItem();
item.title = jQuery(this).find('title').eq(0).text();
item.link = jQuery(this).find('link').eq(0).text();
item.description = jQuery(this).find('description').eq(0).text();
item.updated = jQuery(this).find('pubDate').eq(0).text();
item.id = jQuery(this).find('guid').eq(0).text();
feed.items.push(item);
});
}
};

+ 54
- 0
xi_news/commands/jFeed-master/test-dist-packed.html View File

@ -0,0 +1,54 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jFeed - jQuery feed parser plugin - test</title>
<script type="text/javascript" src="jquery/jquery.js"></script>
<script type="text/javascript" src="build/dist/jquery.jfeed.pack.js"></script>
<script type="text/javascript">
jQuery(function() {
var feedsUrls = ['xml/rss-091.xml',
'xml/rss-092.xml',
'xml/rss-10.xml',
'xml/rss-20.xml',
'xml/atom.xml'];
for(var i = 0; i < feedsUrls.length; i++) {
jQuery.getFeed({url: feedsUrls[i], success: function(feed) {
console.log('feed type: ' + feed.type);
console.log('feed version: ' + feed.version);
console.log('feed title: ' + feed.title);
console.log('feed link: ' + feed.link);
console.log('feed description: ' + feed.description);
console.log('feed language: ' + feed.language);
console.log('feed updated: ' + feed.updated);
console.log('feed items: ' + feed.items.length);
for(var j = 0; j < feed.items.length; j++) {
console.log('item ' + j + ' title: ' + feed.items[j].title);
console.log('item ' + j + ' link: ' + feed.items[j].link);
console.log('item ' + j + ' description: '
+ feed.items[j].description);
console.log('item ' + j + ' updated: ' + feed.items[j].updated);
console.log('item ' + j + ' id: ' + feed.items[j].id);
}
}
});
}
});
</script>
</head>
<body>
<h1>jFeed - jQuery feed parser plugin - test</h1>
<p>Please open Firefox + Firebug console</p>
</body>
</html>

+ 54
- 0
xi_news/commands/jFeed-master/test-dist.html View File

@ -0,0 +1,54 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jFeed - jQuery feed parser plugin - test</title>
<script type="text/javascript" src="jquery/jquery.js"></script>
<script type="text/javascript" src="build/dist/jquery.jfeed.js"></script>
<script type="text/javascript">
jQuery(function() {
var feedsUrls = ['xml/rss-091.xml',
'xml/rss-092.xml',
'xml/rss-10.xml',
'xml/rss-20.xml',
'xml/atom.xml'];
for(var i = 0; i < feedsUrls.length; i++) {
jQuery.getFeed({url: feedsUrls[i], success: function(feed) {
console.log('feed type: ' + feed.type);
console.log('feed version: ' + feed.version);
console.log('feed title: ' + feed.title);
console.log('feed link: ' + feed.link);
console.log('feed description: ' + feed.description);
console.log('feed language: ' + feed.language);
console.log('feed updated: ' + feed.updated);
console.log('feed items: ' + feed.items.length);
for(var j = 0; j < feed.items.length; j++) {
console.log('item ' + j + ' title: ' + feed.items[j].title);
console.log('item ' + j + ' link: ' + feed.items[j].link);
console.log('item ' + j + ' description: '
+ feed.items[j].description);
console.log('item ' + j + ' updated: ' + feed.items[j].updated);
console.log('item ' + j + ' id: ' + feed.items[j].id);
}
}
});
}
});
</script>
</head>
<body>
<h1>jFeed - jQuery feed parser plugin - test</h1>
<p>Please open Firefox + Firebug console</p>
</body>
</html>

+ 64
- 0
xi_news/commands/jFeed-master/test-src.html View File

@ -0,0 +1,64 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jFeed - jQuery feed parser plugin - test</title>
<script type="text/javascript" src="jquery/jquery.js"></script>
<script type="text/javascript" src="src/jfeed.js"></script>
<script type="text/javascript" src="src/jfeeditem.js"></script>
<script type="text/javascript" src="src/jatom.js"></script>
<script type="text/javascript" src="src/jrss.js"></script>
<script type="text/javascript">
jQuery(function() {
var feedsUrls = ['xml/rss-091.xml',
'xml/rss-092.xml',
'xml/rss-10.xml',
'xml/rss-20.xml',
'xml/atom.xml'];
jQuery().ajaxError(function(request, settings, ex) {
console.log('Request error');
for(var i in ex) {
console.log(i + ': ' + ex[i]);
}
});
for(var i = 0; i < feedsUrls.length; i++) {
jQuery.getFeed({url: feedsUrls[i], success: function(feed) {
console.log('feed type: ' + feed.type);
console.log('feed version: ' + feed.version);
console.log('feed title: ' + feed.title);
console.log('feed link: ' + feed.link);
console.log('feed description: ' + feed.description);
console.log('feed language: ' + feed.language);
console.log('feed updated: ' + feed.updated);
console.log('feed items: ' + feed.items.length);
for(var j = 0; j < feed.items.length; j++) {
console.log('item ' + j + ' title: ' + feed.items[j].title);
console.log('item ' + j + ' link: ' + feed.items[j].link);
console.log('item ' + j + ' description: '
+ feed.items[j].description);
console.log('item ' + j + ' updated: ' + feed.items[j].updated);
console.log('item ' + j + ' id: ' + feed.items[j].id);
}
}
});
}
});
</script>
</head>
<body>
<h1>jFeed - jQuery feed parser plugin - test</h1>
<p>Please open Firefox + Firebug console</p>
</body>
</html>

+ 157
- 0
xi_news/commands/jFeed-master/xml/atom.xml View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet href="http://www.atomenabled.org/css/atom.css" type="text/css"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
<title type="html">AtomEnabled.org</title>
<subtitle type="html">Your one stop shop for all Atom API and syndication information.</subtitle>
<link href="http://www.atomenabled.org/atom.xml" rel="self"/>
<icon>http://www.atomenabled.org/favicon.ico</icon>
<link href="http://www.atomenabled.org" rel="alternate" title="AtomEnabled.org" type="text/html"/>
<id>tag:blogger.com,1999:blog-6356614</id>
<updated>2006-09-23T19:44:56Z</updated>
<generator uri="http://www.blogger.com/" version="6.72">Blogger</generator>
<div class="info" xmlns="http://www.w3.org/1999/xhtml">This is an Atom formatted XML site feed. It is intended to be viewed in a Newsreader or syndicated to another site. Please visit the <a href="http://help.blogger.com/bin/answer.py?answer=697">Blogger Help</a> for more info.</div>
<convertLineBreaks xmlns="http://www.blogger.com/atom/ns#">false</convertLineBreaks>
<entry xmlns="http://www.w3.org/2005/Atom">
<author>
<name>Sam Ruby</name>
</author>
<published>2006-09-23T12:42:00-07:00</published>
<updated>2006-09-23T19:44:56Z</updated>
<link href="http://www.atomenabled.org/2006/09/moving-toward-atom.php" rel="alternate" title="Moving Toward Atom" type="text/html"/>
<id>tag:blogger.com,1999:blog-6356614.post-115904069601028798</id>
<title type="html">Moving Toward Atom</title>
<content type="xhtml" xml:base="http://www.atomenabled.org" xml:space="preserve">
<div xmlns="http://www.w3.org/1999/xhtml">The US Intelligence Community Metadata Working Group has issued a <a href="https://dnidata.org/education/xnotes/RSS_and_Atom_Considerations.xml">recommendation</a> that the Intelligence Community, over time, move toward adoption of Atom Syndication Format as the Community’s standard XML-based language for syndication feeds.</div>
</content>
<draft xmlns="http://purl.org/atom-blog/ns#">false</draft>
</entry>
<entry xmlns="http://www.w3.org/2005/Atom">
<author>
<name>Sam Ruby</name>
</author>
<published>2006-08-04T13:50:00-07:00</published>
<updated>2006-08-04T20:53:17Z</updated>
<link href="http://www.atomenabled.org/2006/08/enabling-atom-10-on-wordpress.php" rel="alternate" title="Enabling Atom 1.0 on Wordpress" type="text/html"/>
<id>tag:blogger.com,1999:blog-6356614.post-115472479762549620</id>
<title type="html">Enabling Atom 1.0 on Wordpress</title>
<content type="xhtml" xml:base="http://www.atomenabled.org" xml:space="preserve">
<div xmlns="http://www.w3.org/1999/xhtml">James Snell has <a href="http://www.snellspace.com/wp/?p=404">posted instructions</a> on how you can produce valid Atom 1.0 feeds with WordPress.</div>
</content>
<draft xmlns="http://purl.org/atom-blog/ns#">false</draft>
</entry>
<entry xmlns="http://www.w3.org/2005/Atom">
<author>
<name>Sam Ruby</name>
</author>
<published>2006-07-29T21:34:00-07:00</published>
<updated>2006-07-30T04:38:20Z</updated>
<link href="http://www.atomenabled.org/2006/07/tri-xml-2006-presentation.php" rel="alternate" title="Tri-XML 2006 presentation" type="text/html"/>
<id>tag:blogger.com,1999:blog-6356614.post-115423429120046231</id>
<title type="html">Tri-XML 2006 presentation</title>
<content type="xhtml" xml:base="http://www.atomenabled.org" xml:space="preserve">
<div xmlns="http://www.w3.org/1999/xhtml">
<a href="http://rollerweblogger.org/page/roller">Dave Johnson</a> gave an <a href="http://rollerweblogger.org/page/roller?entry=tri_xml_2006_presentation">excellent talk</a> on the Atom feed format and Atom Publishing Protocol. Here's the abstract:
<blockquote>
<span style="font-weight: bold;">Beyond blogging: Atom format and protocol</span>. Like XML-RPC and SOAP before, feeds and publishing protocols were born in the blogopshere and quickly moved beyond blogging. Nowadays, web service providers are using RSS/Atom feeds and REST-based publishing protocols as lightweight alternatives to SOAP. And developers are finding new ways to combine web services from different sites into new applications, known as "mash-ups" in the lingo of Web 2.0. If you'd like to do the same, then attend this talk to learn about the new IETF Atom feed format (RFC-4287) and the soon-to-be-finalized Atom protocol, which together form a strong foundation for REST-based web services development.
</blockquote>Check it out!</div>
</content>
<draft xmlns="http://purl.org/atom-blog/ns#">false</draft>
</entry>
<entry xmlns="http://www.w3.org/2005/Atom">
<author>
<name>Sam Ruby</name>
</author>
<published>2006-07-19T14:39:00-07:00</published>
<updated>2006-07-19T23:22:18Z</updated>
<link href="http://www.atomenabled.org/2006/07/atomenabled-bloggers.php" rel="alternate" title="AtomEnabled Bloggers" type="text/html"/>
<id>tag:blogger.com,1999:blog-6356614.post-115334590123672226</id>
<title type="html">AtomEnabled Bloggers</title>
<content type="xhtml" xml:base="http://www.atomenabled.org" xml:space="preserve">
<div xmlns="http://www.w3.org/1999/xhtml">The following <a href="http://www.blogger.com/">Blogger</a>-generated but independently hosted weblogs have upgraded to <a href="http://www.ietf.org/rfc/rfc4287">Atom 1.0</a>:<ul>
<li>
<a href="http://atomenabled.org/">AtomEnabled.org</a>
</li>
<li>
<a href="http://ceciliaschola.org/">St. Cecilia Schola Cantorum</a>
</li>
<li>
<a href="http://robweir.com/blog/">An Antic Disposition</a>
</li>
</ul>
<p>If your have a blogger-generated but independently hosted weblog, and your host supports PHP, you too can be on this list.</p>
<ol>
<li>
<p>
<b>Install the script</b>
</p>
<p>
<a href="http://intertwingly.net/stories/2006/04/27/atom.php">Download</a> the script, and upload as <code style="font-size: larger;">atom.php</code>. This file should go in the same directory as your weblog.</p>
</li>
<li>
<p>
<b>Promote the new feed</b>
</p>
<p>This can be done in one of two ways:</p>
<ol style="list-style-type: lower-alpha; list-style-image: none; list-style-position: outside;">
<li>
<p>
<b>Redirect</b>
</p>
<p>This is the most complete and comprehensive approach, however not all hosting providers allow users this level of control over the web server. If yours does, try adding the following to a file named <code style="font-size: larger;">.htaccess</code> to the same directory that you placed the <code style="font-size: larger;">atom.php</code>:</p>
<pre style="font-size: larger; margin-left: 3em;">Redirect atom.xml http://<em>your.host.name</em>/<em>path-to-blog</em>/atom.php</pre>
<p>
<b>Notes:</b> these instructions are for the Apache Web Server. Instructions for other web servers, including Microsoft's IIS will differ. You will need to tailor <em>your.host.name</em> and <em>path-to-blog</em>.</p>
</li>
<li>
<p>
<b>Advertise</b>
</p>
<p>The other approach is to direct your existing and new subscribers to this new feed. Mention the change on your weblog. Update your auto-discovery and other links. To update your links, go into Settings / Site Feed (pictured below)<a href="http://www.atomenabled.org/uploaded_images/BloggerSiteSettings-767978.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"/>
</p>
<a href="http://www.atomenabled.org/uploaded_images/BloggerSiteSettings-767978.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}">
<img alt="Blogger Site Settings" border="0" src="http://www.atomenabled.org/uploaded_images/BloggerSiteSettings-756299.png" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;"/>
</a>
<p>Once you have navigated to that page, change the <b>Site Feed URL</b> to read:</p>
<pre style="font-size: larger; margin-left: 3em;">http://<em>your.host.name</em>/<em>path-to-blog</em>/atom.php</pre>
<p>
<b>Notes:</b> You will need to tailor <em>your.host.name</em> and <em>path-to-blog</em>. You may also have other references on your template that need to be updated. Once complete, republish your blog via the Posting / Status tab.</p>
</li>
</ol>
</li>
</ol>
<p>If you have another Blogger produced site that has upgraded to Atom 1.0, feel free to leave a pointer to your site on the <a href="http://www.intertwingly.net/wiki/pie/AtomEnabledBloggers">Atom wiki</a>. Once your feed has been verified, this weblog post will be updated.</p>
</div>
</content>
<draft xmlns="http://purl.org/atom-blog/ns#">false</draft>
</entry>
<entry xmlns="http://www.w3.org/2005/Atom">
<author>
<name>Sam Ruby</name>
</author>
<published>2005-09-15T06:27:00-07:00</published>
<updated>2005-09-15T13:33:06Z</updated>
<link href="http://www.atomenabled.org/2005/09/atomenableds-atom-feed.php" rel="alternate" title="AtomEnabled's Atom Feed" type="text/html"/>
<id>tag:blogger.com,1999:blog-6356614.post-112679118686717868</id>
<title type="html">AtomEnabled's Atom Feed</title>
<content type="xhtml" xml:base="http://www.atomenabled.org" xml:space="preserve">
<div xmlns="http://www.w3.org/1999/xhtml">This site's <a href="http://www.atomenabled.org/atom.xml">Atom feed</a> has been converted to Atom 1.0. Addionally, the Feed Validator is <a href="http://feedvalidator.org/news/archives/2005/09/15/atom_03_deprecated.html">now issuing deprecation warnings</a> whenever it encounters Atom 0.3 feeds.</div>
</content>
<draft xmlns="http://purl.org/atom-blog/ns#">false</draft>
</entry>
</feed>

+ 54
- 0
xi_news/commands/jFeed-master/xml/rss-091.xml View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="0.91">
<channel>
<title>WriteTheWeb</title>
<link>http://writetheweb.com</link>
<description>News for web users that write back</description>
<language>en-us</language>
<copyright>Copyright 2000, WriteTheWeb team.</copyright>
<managingEditor>editor@writetheweb.com</managingEditor>
<webMaster>webmaster@writetheweb.com</webMaster>
<image>
<title>WriteTheWeb</title>
<url>http://writetheweb.com/images/mynetscape88.gif</url>
<link>http://writetheweb.com</link>
<width>88</width>
<height>31</height>
<description>News for web users that write back</description>
</image>
<item>
<title>Giving the world a pluggable Gnutella</title>
<link>http://writetheweb.com/read.php?item=24</link>
<description>WorldOS is a framework on which to build programs that work like Freenet or Gnutella -allowing distributed applications using peer-to-peer routing.</description>
</item>
<item>
<title>Syndication discussions hot up</title>
<link>http://writetheweb.com/read.php?item=23</link>
<description>After a period of dormancy, the Syndication mailing list has become active again, with contributions from leaders in traditional media and Web syndication.</description>
</item>
<item>
<title>Personal web server integrates file sharing and messaging</title>
<link>http://writetheweb.com/read.php?item=22</link>
<description>The Magi Project is an innovative project to create a combined personal web server and messaging system that enables the sharing and synchronization of information across desktop, laptop and palmtop devices.</description>
</item>
<item>
<title>Syndication and Metadata</title>
<link>http://writetheweb.com/read.php?item=21</link>
<description>RSS is probably the best known metadata format around. RDF is probably one of the least understood. In this essay, published on my O'Reilly Network weblog, I argue that the next generation of RSS should be based on RDF.</description>
</item>
<item>
<title>UK bloggers get organised</title>
<link>http://writetheweb.com/read.php?item=20</link>
<description>Looks like the weblogs scene is gathering pace beyond the shores of the US. There's now a UK-specific page on weblogs.com, and a mailing list at egroups.</description>
</item>
<item>
<title>Yournamehere.com more important than anything</title>
<link>http://writetheweb.com/read.php?item=19</link>
<description>Whatever you're publishing on the web, your site name is the most valuable asset you have, according to Carl Steadman.</description>
</item>
</channel>
</rss>

+ 38
- 0
xi_news/commands/jFeed-master/xml/rss-092.xml View File

@ -0,0 +1,38 @@
<?xml version="1.0"?>
<!-- RSS generation done by 'Radio UserLand' on Fri, 13 Apr 2001 19:23:02 GMT -->
<rss version="0.92">
<channel>
<title>Dave Winer: Grateful Dead</title>
<link>http://www.scripting.com/blog/categories/gratefulDead.html</link>
<description>A high-fidelity Grateful Dead song every day. This is where we're experimenting with enclosures on RSS news items that download when you're not using your computer. If it works (it will) it will be the end of the Click-And-Wait multimedia experience on the Internet. </description>
<lastBuildDate>Fri, 13 Apr 2001 19:23:02 GMT</lastBuildDate>
<docs>http://backend.userland.com/rss092</docs>
<managingEditor>dave@userland.com (Dave Winer)</managingEditor>
<webMaster>dave@userland.com (Dave Winer)</webMaster>
<cloud domain="data.ourfavoritesongs.com" port="80" path="/RPC2" registerProcedure="ourFavoriteSongs.rssPleaseNotify" protocol="xml-rpc"/>
<item>
<description>It's been a few days since I added a song to the Grateful Dead channel. Now that there are all these new Radio users, many of whom are tuned into this channel (it's #16 on the hotlist of upstreaming Radio users, there's no way of knowing how many non-upstreaming users are subscribing, have to do something about this..). Anyway, tonight's song is a live version of Weather Report Suite from Dick's Picks Volume 7. It's wistful music. Of course a beautiful song, oft-quoted here on Scripting News. &lt;i&gt;A little change, the wind and rain.&lt;/i&gt;
</description>
<enclosure url="http://www.scripting.com/mp3s/weatherReportDicksPicsVol7.mp3" length="6182912" type="audio/mpeg"/>
</item>
<item>
<description>Kevin Drennan started a &lt;a href="http://deadend.editthispage.com/"&gt;Grateful Dead Weblog&lt;/a&gt;. Hey it's cool, he even has a &lt;a href="http://deadend.editthispage.com/directory/61"&gt;directory&lt;/a&gt;. &lt;i&gt;A Frontier 7 feature.&lt;/i&gt;</description>
<source url="http://scriptingnews.userland.com/xml/scriptingNews2.xml">Scripting News</source>
</item>
<item>
<description>&lt;a href="http://arts.ucsc.edu/GDead/AGDL/other1.html"&gt;The Other One&lt;/a&gt;, live instrumental, One From The Vault. Very rhythmic very spacy, you can listen to it many times, and enjoy something new every time.</description>
<enclosure url="http://www.scripting.com/mp3s/theOtherOne.mp3" length="6666097" type="audio/mpeg"/>
</item>
<item>
<description>This is a test of a change I just made. Still diggin..</description>
</item>
<item>
<description>The HTML rendering almost &lt;a href="http://validator.w3.org/check/referer"&gt;validates&lt;/a&gt;. Close. Hey I wonder if anyone has ever published a style guide for ALT attributes on images? What are you supposed to say in the ALT attribute? I sure don't know. If you're blind send me an email if u cn rd ths. </description>
</item>
</channel>
</rss>

+ 53
- 0
xi_news/commands/jFeed-master/xml/rss-10.xml View File

@ -0,0 +1,53 @@
<?xml version="1.0"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
>
<channel rdf:about="http://www.xml.com/xml/news.rss">
<title>XML.com</title>
<link>http://xml.com/pub</link>
<description>
XML.com features a rich mix of information and services
for the XML community.
</description>
<image rdf:resource="http://xml.com/universal/images/xml_tiny.gif" />
<items>
<rdf:Seq>
<rdf:li resource="http://xml.com/pub/2000/08/09/xslt/xslt.html" />
<rdf:li resource="http://xml.com/pub/2000/08/09/rdfdb/index.html" />
</rdf:Seq>
</items>
</channel>
<image rdf:about="http://xml.com/universal/images/xml_tiny.gif">
<title>XML.com</title>
<link>http://www.xml.com</link>
<url>http://xml.com/universal/images/xml_tiny.gif</url>
</image>
<item rdf:about="http://xml.com/pub/2000/08/09/xslt/xslt.html">
<title>Processing Inclusions with XSLT</title>
<link>http://xml.com/pub/2000/08/09/xslt/xslt.html</link>
<description>
Processing document inclusions with general XML tools can be
problematic. This article proposes a way of preserving inclusion
information through SAX-based processing.
</description>
</item>
<item rdf:about="http://xml.com/pub/2000/08/09/rdfdb/index.html">
<title>Putting RDF to Work</title>
<link>http://xml.com/pub/2000/08/09/rdfdb/index.html</link>
<description>
Tool and API support for the Resource Description Framework
is slowly coming of age. Edd Dumbill takes a look at RDFDB,
one of the most exciting new RDF toolkits.
</description>
</item>
</rdf:RDF>

+ 47
- 0
xi_news/commands/jFeed-master/xml/rss-20.xml View File

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Liftoff News</title>
<link>http://liftoff.msfc.nasa.gov/</link>
<description>Liftoff to Space Exploration.</description>
<language>en-us</language>
<pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate>
<lastBuildDate>Tue, 10 Jun 2003 09:41:01 GMT</lastBuildDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>Weblog Editor 2.0</generator>
<managingEditor>editor@example.com</managingEditor>
<webMaster>webmaster@example.com</webMaster>
<item>
<title>Star City</title>
<link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp</link>
<description>How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's &lt;a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm"&gt;Star City&lt;/a&gt;.</description>
<pubDate>Tue, 03 Jun 2003 09:39:21 GMT</pubDate>
<guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid>
</item>
<item>
<description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a &lt;a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm"&gt;partial eclipse of the Sun&lt;/a&gt; on Saturday, May 31st.</description>
<pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate>
<guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid>
</item>
<item>
<title>The Engine That Does More</title>
<link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link>
<description>Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly. The proposed VASIMR engine would do that.</description>
<pubDate>Tue, 27 May 2003 08:37:32 GMT</pubDate>
<guid>http://liftoff.msfc.nasa.gov/2003/05/27.html#item571</guid>
</item>
<item>
<title>Astronauts' Dirty Laundry</title>
<link>http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp</link>
<description>Compared to earlier spacecraft, the International Space Station has many luxuries, but laundry facilities are not one of them. Instead, astronauts have other options.</description>
<pubDate>Tue, 20 May 2003 08:56:02 GMT</pubDate>
<guid>http://liftoff.msfc.nasa.gov/2003/05/20.html#item570</guid>
</item>
</channel>
</rss>

+ 2
- 0
xi_news/commands/jquery-3.5.1.min.js
File diff suppressed because it is too large
View File


+ 67
- 0
xi_news/main.js View File

@ -0,0 +1,67 @@
const fs = require('fs')
const Discord = require('discord.js');
const Client = require('./client');
const fetch = require("node-fetch");
const {
prefix,
token,
} = require('./config.json');
const client = new Client();
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
console.log(client.commands);
client.once('ready', () => {
console.log('Ready!');
});
client.once('reconnecting', () => {
console.log('Reconnecting!');
});
client.once('disconnect', () => {
console.log('Disconnect!');
});
client.on('message', async message => {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) return;
const command = client.commands.get(commandName);
const permitted_roles = client.commands.get(commandName)["roles"];
has_roles = false
if (permitted_roles){
for(i = 0; i < permitted_roles.length; i++){
if(message.member.roles.cache.has(permitted_roles[i])){
has_roles = true
}
}
if (!has_roles && permitted_roles.length != 0){
message.reply('You are not allowed to run this command!');
return;
}
}
try {
command.execute(message);
} catch (error) {
console.error(error);
message.reply('There was an error trying to execute that command!');
}
});
client.login(token);

+ 1163
- 0
xi_news/package-lock.json
File diff suppressed because it is too large
View File


+ 28
- 0
xi_news/package.json View File

@ -0,0 +1,28 @@
{
"name": "xi_master",
"version": "1.0.0",
"description": "A master music bot for our xi network discord server",
"author": "Fringe <yigit@yigitcolakoglu.com>",
"main": "main.js",
"scripts": {
"start": "node main.js"
},
"dependencies": {
"@discordjs/opus": "^0.1.0",
"cheerio": "^1.0.0-rc.3",
"discord.js": "^12.2.0",
"ffmpeg": "0.0.4",
"fluent-ffmpeg": "^2.1.2",
"googleapis": "*",
"jquery": "^3.5.1",
"jquery-rss": "^4.3.0",
"jsdom": "^16.3.0",
"node-fetch": "^2.6.0",
"node-opus": "^0.3.3",
"request": "^2.88.2",
"rss-parser": "^3.8.0",
"type": "module",
"vanilla-rss": "^1.4.0",
"ytdl-core": "^3.0.0"
}
}

+ 1
- 0
xi_tracker/.gitignore View File

@ -0,0 +1 @@
node_modules

+ 15
- 0
xi_tracker/Dockerfile View File

@ -0,0 +1,15 @@
FROM node:lts
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
# If you are building your code for production
# # RUN npm ci --only=production
COPY . .
CMD [ "node", "main.js" ]

+ 28
- 0
xi_tracker/Locations list.txt View File

@ -0,0 +1,28 @@
Locations list:
1.Organisation 56/68
2.Domain 732/58
3.SPF records 1216/64
4.Subdomain bruteforce 1216/283
5.passive DNS 1216/520
6.assetfinder + plausability check 1216/742
7.Resolve 2202/330
8.List of Subdomains 2014/666
9.altdns 2391/666
10.IPS 2932/328
11.Masscan all TCP ports 3309/333
12.VHost discovery 2932/666
13.Open ports 3721/333
14.GetAllURLs 969/1116
15.Check Github 967/1341
16.Search Engines 966/1566
17.Subdomain Takeover 2020/1084
18.httprobe 2392/1084
19.List of IPs with HTTP=service 3196/1076
20.Nmap service enumeratiom 4200/549
21.Vulnerability scan4200/987
22.Login brute force 4590/990
In our house, our only source of income is my dad. Since the outbreak we have experienced a recession nationwide, effecting my daily live. On top of that, I'm currently

+ 16
- 0
xi_tracker/client.js View File

@ -0,0 +1,16 @@
const { Client, Collection } = require('discord.js');
module.exports = class extends Client {
constructor(config) {
super({
disableEveryone: true,
disabledEvents: ['TYPING_START'],
});
this.commands = new Collection();
this.queue = new Map();
this.config = config;
}
};

+ 27
- 0
xi_tracker/commands/down.js View File

@ -0,0 +1,27 @@
module.exports = {
name: 'downgrade',
channels: ['734387503464710165'],
description: 'Downgrade a user!',
roles: ['732345527143759943'],
execute(message,args) {
var roles_hierarchy = [
'732558019409346603', // 'kiddie,
'732618552661770241', // 'hunter',
'732618853355356192', // 'hacker',
'732618650158366770' // 'mentor'
];
var current_index = null
const member = message.mentions.members.first();
roles_hierarchy.forEach(function(item, index){
if (member._roles[0] == item) current_index = index;
});
if(current_index == 0){
return message.channel.send("This user is already at the lowest level!")
}
console.log(current_index);
member.roles.remove(roles_hierarchy[current_index]);
member.roles.add(roles_hierarchy[current_index - 1]);
return message.channel.send("User downgraded successfully!")
},
};

+ 94
- 0
xi_tracker/commands/email.js View File

@ -0,0 +1,94 @@
const {
mongo_url,
trello_token,
trello_key
} = require('../config.json');
const {
userModel,
teamModel,
} = require('./schemas.js');
let mongoose = require('mongoose');
var Trello = require('trello-node-api')(trello_key, trello_token);
const fetch = require('node-fetch');
module.exports = {
name: 'email',
channels: ['dm'],
description: 'Update the email address of the user',
async execute(message) {
let email = message.content.split(" ")[1];
if(!email){
return message.reply("You must supply an email!")
}
if(!/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)){
return message.reply("You must supply an email address, not some other input!.");
}
var member_id = message.author.id;
try {
await mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
}catch (error) {
console.log("ERROR WITH MONGODB CONNECTION");
}
const user_data = await userModel.find({_id: member_id}, "team_id email trello_id");
if(user_data.length == 0){
return message.reply("You should be a member of the ξ.network discord channel to run this command!")
}
if(user_data[0].email && user_data[0].team_id !== 0){
console.log("Deleting user")
let team_data = await teamModel.find({_id: user_data[0].team_id}, "board_id");
await fetch(`https://api.trello.com/1/boards/${team_data[0].board_id}/members/${user_data[0].trello_id}?key=${trello_key}&token=${trello_token}`, {
method: 'DELETE'
})
.catch(err => console.error(err));
}
if(user_data[0].team_id !== "0"){
let team_data = await teamModel.find({_id: user_data[0].team_id}, "board_id creator");
let type = "normal";
if(team_data[0].creator == member_id){
type = "admin"
}
let addition = await fetch(`https://api.trello.com/1/boards/${team_data[0].board_id}/members?key=${trello_key}&token=${trello_token}&email=${email}&type=${type}`, {
method: 'PUT',
})
.catch(err => console.error(err));
let data = await addition.json()
let result = await userModel.findOneAndUpdate(
{_id: member_id},
{email: email, trello_id: data.memberships[data.memberships.length - 1].idMember},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
}else{
userModel.findOneAndUpdate(
{_id: member_id},
{email: email},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
}
message.reply("Email set successfully! You should receive an invite email from trello if you are a member of a team.")
},
};

+ 45
- 0
xi_tracker/commands/role_message.js View File

@ -0,0 +1,45 @@
module.exports = {
name: 'role_message',
channels: ['734387503464710165'],
description: 'Send the role message!',
roles: ['732345527143759943'],
async execute(message) {
let message_new = await message.client.channels.cache.get("734387503464710165").send(`React to this message to give yourself a role.
:iphone: : mobile development
:nut_and_bolt: : hardware development
:factory: : backend development
:eyeglasses: : frontend development
:spider:(spider) : web development
:globe_with_meridians: : network engineering
:penguin: : unix/linux
:spider_web: : web security
:closed_lock_with_key: : cryptology
:upside_down: : reverse engineering
:police_officer: : network security
`)
Promise.all([
message_new.react('🔐'),
message_new.react('🙃'),
message_new.react('📱'),
message_new.react('🔩'),
message_new.react('🕸️'),
message_new.react('🏭'),
message_new.react('🕷️'),
message_new.react('🌐'),
message_new.react('👮'),
message_new.react('🐧')
])
.catch(() => console.error('One of the emojis failed to react.'));
}
}

+ 26
- 0
xi_tracker/commands/schemas.js View File

@ -0,0 +1,26 @@
let mongoose = require('mongoose')
module.exports = {
userModel : mongoose.model('users', new mongoose.Schema({
_id: String,
joined_at: Number,
team_id: String,
profession: Array,
rank: Number,
xp: Number,
email: String,
trello_id: String
})),
teamModel: mongoose.model('teams', new mongoose.Schema({
_id: mongoose.Types.ObjectId,
team_name: String,
creator: String,
mods: Array,
member_role: String,
mod_role: String,
text_channel: String,
voice_channel: String,
board_id: String
}))
}

+ 53
- 0
xi_tracker/commands/team_close.js View File

@ -0,0 +1,53 @@
const {
mongo_url,
trello_token,
trello_key
} = require('../config.json');
const {
userModel,
teamModel,
} = require('./schemas.js');
let mongoose = require('mongoose');
let Trello = require('trello-node-api')(trello_key, trello_token);
module.exports = {
name: 'close',
family: 'team',
channels: ['734387503464710165'],
description: 'Close the team! ',
async execute(message) {
var member_id = message.member.id;
try {
await mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null);
}catch (error) {
console.log("could not connect");
}
const user_data = await userModel.find({_id: member_id},"team_id trello_id email");
const team_id = user_data[0].team_id
if(team_id == '0'){
return message.reply('You must be in a team to quit!');
}
var teamdata = await teamModel.find({ _id :team_id },'member_role mod_role text_channel voice_channel mods board_id');
var team = teamdata[0];
message.guild.roles.fetch(team.member_role).then((role) => role.delete());
message.guild.roles.fetch(team.mod_role).then((role) => role.delete());
message.client.channels.fetch(team.text_channel).then((channel) => channel.delete());
message.client.channels.fetch(team.voice_channel).then((channel) => channel.delete());
let old_team = new teamModel(team);
old_team.remove();
Trello.board.del(team.board_id)
.catch(function (error) {
console.log('error', error);
});
userModel.updateMany({team_id: team_id}, { team_id: 0 }, function(err, res) {});
message.channel.send("Team closed successfully!")
},
}

+ 159
- 0
xi_tracker/commands/team_create.js View File

@ -0,0 +1,159 @@
const {
mongo_url,
trello_token,
trello_key
} = require('../config.json');
const {
userModel,
teamModel,
} = require('./schemas.js');
let mongoose = require('mongoose');
var Trello = require('trello-node-api')(trello_key, trello_token);
const fetch = require('node-fetch');
const { strict } = require('assert');
const { parse } = require('path');
const allowed_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
module.exports = {
name: 'create',
family: 'team',
channels: ['734387503464710165'],
description: 'Create a team',
async execute(message) {
let team_name = message.content.split(" ")[2];
if(!team_name){
return message.reply("You must supply a team name!")
}
if(team_name.length > 20){
return message.reply("Team names can be 20 letters max.");
}
for (let i = 0; i < team_name.length; i++) {
if(allowed_chars.indexOf(team_name.charAt(i)) == -1){
return message.reply("Team names can only have letters and underscore");
}
}
var member_id = message.member.id;
try {
await mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
}catch (error) {
console.log("ERROR WITH MONGODB CONNECTION");
}
const user_data = await userModel.find({_id: member_id}, "team_id email");
team = user_data[0].team_id
if(team !== '0'){
return message.reply("You already are in a team!")
}
const teams_search = await teamModel.find({team_name: team_name}, "id")
if(teams_search.length != 0){
return message.reply("A team with that name already exists!")
}
let regular_role = await message.guild.roles.create({
data: {
name: team_name,
color: 'AQUA',
},
reason: 'This is the role for the members of ' + team_name,
})
let mod_role = await message.guild.roles.create({
data: {
name: team_name + "-mod",
color: 'LUMINOUS_VIVID_PINK',
},
reason: 'This is the role for the mods of ' + team_name,
})
let text_channel = await message.guild.channels.create(team_name, {
type: 'text',
permissionOverwrites: [
{
id: regular_role.id,
allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ATTACH_FILES', 'EMBED_LINKS'],
},
{
id: mod_role.id,
allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ATTACH_FILES', 'EMBED_LINKS', 'MENTION_EVERYONE', 'MANAGE_MESSAGES', ],
},
],
});
let voice_channel = await message.guild.channels.create(team_name, {
type: 'voice',
permissionOverwrites: [
{
id: regular_role.id,
allow: ['CONNECT', 'SPEAK'],
},
{
id: mod_role.id,
allow: ['CONNECT', 'SPEAK', 'MUTE_MEMBERS', 'STREAM', 'PRIORITY_SPEAKER' ],
},
],
});
message.member.roles.add(mod_role.id);
text_channel.setParent('734080794783383635', { lockPermissions: false })
voice_channel.setParent('734080915122290778', { lockPermissions: false })
board = await Trello.board.create({name: team_name + " TODOS"})
let id = mongoose.Types.ObjectId();
let new_team = new teamModel({
_id: id,
team_name: team_name,
creator: member_id,
member_role: regular_role.id,
mod_role: mod_role.id,
text_channel: text_channel.id,
voice_channel: voice_channel.id,
board_id: board.id
})
await new_team.save();
await userModel.findOneAndUpdate(
{_id: member_id},
{team_id: id},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
if(!user_data[0].email){
message.author.send("You were added to a team but do not have an email on the system. You need an email to access the trello board! Add your email after the !email prefix to set your email address.")
}else{
let addition = await fetch(`https://api.trello.com/1/boards/${board.id}/members?key=${trello_key}&token=${trello_token}&email=${user_data[0].email}&type=admin`, {
method: 'PUT'
})
.catch(err => console.error(err));
let data = await addition.json()
let result = await userModel.findOneAndUpdate(
{_id: member_id},
{email: user_data[0].email, trello_id: data.members[data.members.length - 1].idMember},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
}
return message.reply("Team created succesfully!")
},
};

+ 77
- 0
xi_tracker/commands/team_elevate.js View File

@ -0,0 +1,77 @@
const {
mongo_url,
trello_token,
trello_key
} = require('../config.json');
const {
userModel,
teamModel,
} = require('./schemas.js');
let mongoose = require('mongoose');
module.exports = {
name: 'elevate',
family: 'team',
channels: ['734387503464710165'],
description: 'Elevate a user in a team ',
async execute(message) {
let targets = message.mentions.members
const member_id = message.member.id;
if(targets.size == 0){
return message.reply("You must supply at least one member!")
}else if(targets.size > 20){
return message.reply("You can elevate at most 20 users!")
}
try {
await mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
}catch (error) {
console.log("ERROR WITH MONGODB CONNECTION");
}
const user_data = await userModel.find({_id: member_id}, "team_id");
if(user_data[0].team_id === "0"){
return message.reply("You must be in a team to elevate a user!");
}
const team_data = await teamModel.find({_id: user_data[0].team_id}, "creator mods team_name member_role mod_role");
const team = team_data[0]
let mods = team.mods
if(member_id !== team.creator && team.mods.indexOf(member_id) === -1){
return message.reply("You do not have enough privileges for this action!")
}
targets.forEach(async(value, key, map) => {
let target_data = await userModel.find({_id: key}, "team_id");
if(target_data[0].team_id == team._id){
let mod_index = team.mods.indexOf(key)
if(mod_index == -1){
value.roles.remove(team.member_role);
value.roles.add(team.mod_role);
mods.push(key);
let result = await teamModel.findOneAndUpdate(
{_id: team._id},
{mods: mods},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
message.channel.send(`Elevated user <@${key}>`)
}else{
message.channel.send(`<@${key}> already elevated!`)
}
}else{
message.channel.send(`Can't elavate user <@${key}>`);
}
});
},
};

+ 103
- 0
xi_tracker/commands/team_kick.js View File

@ -0,0 +1,103 @@
const {
mongo_url,
trello_token,
trello_key
} = require('../config.json');
const {
userModel,
teamModel,
} = require('./schemas.js');
let mongoose = require('mongoose');
const fetch = require('node-fetch');
module.exports = {
name: 'kick',
family: 'team',
channels: ['734387503464710165'],
description: 'Add user to team',
async execute(message) {
let targets = message.mentions.members
const member_id = message.member.id;
if(targets.size == 0){
return message.reply("You must supply at least one member!")
}else if(targets.size > 20){
return message.reply("You can add at most 20 users!")
}
try {
await mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
}catch (error) {
console.log("ERROR WITH MONGODB CONNECTION");
}
const user_data = await userModel.find({_id: member_id}, "team_id");
if(user_data[0].team_id === "0"){
return message.reply("You must be in a team to kick a user!");
}
const team_data = await teamModel.find({_id: user_data[0].team_id},
"creator board_id mods team_name member_role mod_role");
const team = team_data[0]
if(member_id !== team.creator && team.mods.indexOf(member_id) === -1){
return message.reply("You do not have enough privileges for this action!")
}
let mods = team.mods
targets.forEach(async(value, key, map) => {
if(key == member_id){
return message.reply("You cannot kick yourself!")
}else if (key == team.creator){
return message.reply("You cannot kick the creator!")
}
let target_data = await userModel.find({_id: key}, "team_id trello_id email");
if(target_data[0].team_id == team._id){
let mod_index = team.mods.indexOf(key)
if(mod_index == -1){
value.roles.remove(team.member_role)
}else{
value.roles.remove(team.mod_role)
mods.splice(mod_index, 1)
let result = await teamModel.findOneAndUpdate(
{_id: team._id},
{mods: mods},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
}
let result = await userModel.findOneAndUpdate(
{_id: key},
{team_id: "0"},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
message.client.users.fetch(key).then((user) => user.send(`You have been kicked from the team ${team.team_name}`))
if(target_data[0].email){
console.log("Deleting user from trello")
await fetch(`https://api.trello.com/1/boards/${team.board_id}/members/${target_data[0].trello_id}?key=${trello_key}&token=${trello_token}`, {
method: 'DELETE'
})
.catch(err => console.error(err));
}
message.channel.send(`Kicked user <@${key}>`)
}else{
message.channel.send(`Can't kick user <@${key}>`);
}
});
},
};

+ 81
- 0
xi_tracker/commands/team_lower.js View File

@ -0,0 +1,81 @@
const {
mongo_url,
trello_token,
trello_key
} = require('../config.json');
const {
userModel,
teamModel,
} = require('./schemas.js');
let mongoose = require('mongoose');
module.exports = {
name: 'lower',
family: 'team',
channel: ['734387503464710165'],
description: 'Lower a user in a team ',
async execute(message) {
let targets = message.mentions.members
const member_id = message.member.id;
if(targets.size == 0){
return message.reply("You must supply at least one member!")
}else if(targets.size > 20){
return message.reply("You can lower at most 20 users!")
}
try {
await mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
}catch (error) {
console.log("ERROR WITH MONGODB CONNECTION");
}
const user_data = await userModel.find({_id: member_id}, "team_id");
if(user_data[0].team_id === "0"){
return message.reply("You must be in a team to lower a user!");
}
const team_data = await teamModel.find({_id: user_data[0].team_id}, "creator mods team_name member_role mod_role");
const team = team_data[0]
let mods = team.mods
if(member_id !== team.creator && team.mods.indexOf(member_id) === -1){
return message.reply("You do not have enough privileges for this action!")
}
targets.forEach(async(value, key, map) => {
let target_data = await userModel.find({_id: key}, "team_id");
if(target_data[0].team_id == team._id){
if(key == member_id){
return message.reply("You cannot lower yourself!")
}else if (key == team.creator){
return message.reply("You cannot lower the creator!")
}
if(mod_index !== -1){
value.roles.add(team.member_role);
value.roles.remove(team.mod_role);
mods.splice(mod_index, 1)
let result = await teamModel.findOneAndUpdate(
{_id: team._id},
{mods: mods},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
message.channel.send(`Lowered user <@${key}>`)
}else{
message.channel.send(`<@${key}> not a mod!`)
}
}else{
message.channel.send(`Can't lower user <@${key}>`);
}
});
},
};

+ 87
- 0
xi_tracker/commands/team_quit.js View File

@ -0,0 +1,87 @@
const {
mongo_url,
trello_token,
trello_key
} = require('../config.json');
const {
userModel,
teamModel,
} = require('./schemas.js');
let mongoose = require('mongoose');
var Trello = require('trello-node-api')(trello_key, trello_token);
const fetch = require('node-fetch');
const { strict } = require('assert');
const { parse } = require('path');
module.exports = {
name: 'quit',
family: 'team',
channels: ['734387503464710165'],
description: 'Quit from a team',
async execute(message) {
var member_id = message.member.id;
try {
await mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null);
}catch (error) {
console.log("could not connect");
}
const user_data = await userModel.find({_id: member_id},"team_id trello_id email");
const team_id = user_data[0].team_id
if(team_id == '0'){
return message.reply('You must be in a team to quit!');
}
const filter = { _id : member_id };
const update = { team_id : '0' };
var def = await userModel.findOneAndUpdate(filter, update,{
new: true,
runValidators: true,
useFindAndModify: false
});
var teamdata = await teamModel.find({ _id :team_id },'member_role mod_role text_channel voice_channel mods board_id');
var team = teamdata[0];
var mods = team.mods;
let mod_index = team.mods.indexOf(member_id)
if(mod_index === -1){
message.member.roles.remove(team.member_role)
}else{
message.member.roles.remove(team.mod_role)
mods.splice(mod_index, 1)
}
teamModel.findOneAndUpdate({_id :team_id},{mods : mods});
if(user_data[0].email){
await fetch(`https://api.trello.com/1/boards/${team.board_id}/members/${user_data[0].trello_id}?key=${trello_key}&token=${trello_token}`, {
method: 'DELETE'
})
.catch(err => console.error(err));
}
let team_members = await userModel.find({team_id: team_id})
if(team_members.length == 0){
message.channel.send("No users left in this team. Deleting");
message.guild.roles.fetch(team.member_role).then((role) => role.delete());
message.guild.roles.fetch(team.mod_role).then((role) => role.delete());
message.client.channels.fetch(team.text_channel).then((channel) => channel.delete());
message.client.channels.fetch(team.voice_channel).then((channel) => channel.delete());
team.mods = mods;
let old_team = new teamModel(team);
old_team.remove();
Trello.board.del(team.board_id)
.catch(function (error) {
console.log('error', error);
});
}
return message.reply('Done!');
},
};

+ 90
- 0
xi_tracker/commands/team_user.js View File

@ -0,0 +1,90 @@
const {
mongo_url,
trello_token,
trello_key
} = require('../config.json');
const {
userModel,
teamModel,
} = require('./schemas.js');
let mongoose = require('mongoose');
const fetch = require('node-fetch');
module.exports = {
name: 'add',
family: 'team',
channels: ['734387503464710165'],
description: 'Add user to team',
async execute(message) {
let targets = message.mentions.members
const member_id = message.member.id;
if(targets.size == 0){
return message.reply("You must supply at least one member!")
}else if(targets.size > 20){
return message.reply("You can add at most 20 users!")
}
try {
await mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
}catch (error) {
console.log("ERROR WITH MONGODB CONNECTION");
}
const user_data = await userModel.find({_id: member_id}, "team_id");
if(user_data[0].team_id === "0"){
return message.reply("You must be in a team to add a user!");
}
const team_data = await teamModel.find({_id: user_data[0].team_id}, "creator mods team_name member_role board_id");
const team = team_data[0]
if(member_id !== team.creator && team.mods.indexOf(member_id) === -1){
return message.reply("You do not have enough privileges for this action!")
}
targets.forEach(async(value, key, map) => {
let target_data = await userModel.find({_id: key}, "team_id email");
if(target_data[0].team_id === "0"){
value.roles.add(team.member_role)
let result = await userModel.findOneAndUpdate(
{_id: key},
{team_id: team._id},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
message.client.users.fetch(key).then((user) => user.send(`You have been added to the team ${team.team_name}`))
if(!target_data[0].email){
message.client.users.fetch(key).then((user) => user.send("You need an email to access the team's trello board! Add your email after the !email prefix to set your email address."))
}else{
let addition = await fetch(`https://api.trello.com/1/boards/${team.board_id}/members?key=${trello_key}&token=${trello_token}&email=${target_data[0].email}&type=normal`, {
method: 'PUT'
})
.catch(err => console.error(err));
let data = await addition.json()
let result = await userModel.findOneAndUpdate(
{_id: key},
{email: target_data[0].email, trello_id: data.memberships[data.memberships.length - 1].idMember},
{
new: true,
runValidators: true,
useFindAndModify: false
}
);
}
message.channel.send(`Added user <@${key}>`)
}else{
message.channel.send(`Can't add user <@${key}>`);
}
});
},
};

+ 28
- 0
xi_tracker/commands/up.js View File

@ -0,0 +1,28 @@
module.exports = {
name: 'upgrade',
channels: ['734387503464710165'],
description: 'Upgrade a user!',
roles: ['732345527143759943'],
execute(message,args) {
var roles_hierarchy = [
'732558019409346603', // 'kiddie,
'732618552661770241', // 'hunter',
'732618853355356192', // 'hacker',
'732618650158366770' // 'mentor'
];
var current_index = null
const member = message.mentions.members.first();
roles_hierarchy.forEach(function(item, index){
if (member._roles[0] == item) current_index = index;
});
if(current_index == roles_hierarchy.length - 1){
return message.channel.send("This user is already at the highest level!")
}
console.log(current_index);
member.roles.remove(roles_hierarchy[current_index])
member.roles.add(roles_hierarchy[current_index + 1]);
return message.channel.send("User upgraded successfully!")
},
};

+ 282
- 0
xi_tracker/main.js View File

@ -0,0 +1,282 @@
const fs = require('fs')
const Discord = require('discord.js');
const Client = require('./client');
let mongoose = require('mongoose');
const {
prefix,
token,
mongo_url,
role_message_id
} = require('./config.json');
const {
userModel,
teamModel,
} = require('./commands/schemas.js');
const client = new Client({ partials: ['MESSAGE', 'CHANNEL', 'REACTION'] });
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
let prefix = ""
if(!command.name) continue;
if(command.family){
prefix = command.family + "_"
}
client.commands.set(prefix + command.name, command);
}
console.log(client.commands);
client.once('ready', async () => {
console.log('Ready!');
async function delete_messages(){
let fetched;
channel = client.channels.cache.get("734387503464710165")
message_manager = channel.messages
do {
fetched = await message_manager.fetch({ limit: 100 });
fetched.delete(role_message_id)
channel.bulkDelete(fetched);
}
while(fetched.size >= 3);
}
await delete_messages();
var minutes = 1, interval = minutes * 60 * 1000;
setInterval(delete_messages, interval);
});
client.once('reconnecting', () => {
console.log('Reconnecting!');
});
client.once('disconnect', () => {
console.log('Disconnect!');
});
client.on('message', async message => {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).split(/ +/);
const c1 = args.shift().toLowerCase();
let c2 = args.shift();
if(c2){
c2 = c2.toLowerCase()
}
var commandName = null;
if (client.commands.has(c1)){
commandName = c1;
}else if(client.commands.has(c1 + "_" + c2)){
commandName = c1 + "_" + c2;
}else{
return;
}
const command = client.commands.get(commandName);
const permitted_roles = client.commands.get(commandName)["roles"];
const permitted_channels = client.commands.get(commandName)["channels"]
has_roles = false
if (permitted_roles){
for(i = 0; i < permitted_roles.length; i++){
if(message.member.roles.cache.has(permitted_roles[i])){
has_roles = true
}
}
if (!has_roles){
message.reply('You are not allowed to run this command!');
return;
}
}
if(permitted_channels){
msg_channel = message.channel;
channel_allowed = false
for(i = 0; i < permitted_channels.length; i++){
if(permitted_channels[i] == "dm" && msg_channel instanceof Discord.DMChannel){
channel_allowed = true;
break;
}else if(permitted_channels[i] == msg_channel.id){
channel_allowed = true;
break;
}
}
if(!channel_allowed){
return;
}
}
try {
command.execute(message,args);
} catch (error) {
console.error(error);
message.reply('There was an error trying to execute that command!');
}
});
client.on('guildMemberAdd', member => {
let new_user = new userModel({
_id: member.id,
joined_at: Date.now(),
team_id: "0",
profession: "",
rank: 1,
xp: 0,
email: "",
trello_id: ""
})
member.guild.channels.cache.get('734387938418360362').send("Welcome <@"+ member.id +">. Xi up!");
member.roles.add('732558019409346603');
try {
mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
let db = mongoose.connection;
db.once("open", function callback () {
new_user.save();
});
}catch (error) {
console.log("ERROR WITH MONGODB CONNECTION");
}
});
const reaction_to_prof = {
"🔐" : ["734453192921710604" ,"Cryptology"],
"🙃" : ["734453691318403072" ,"Reverse Engineer"],
"📱" : ["734453796306026576" ,"Mobile Developer"],
"🔩" : ["734453830669959218" ,"Hardware Developer"],
"🕸️" : ["734453917345120316" ,"Web security Expert"],
"🏭" : ["734453944700502186" ,"Backend Developer"],
"🕷️" : ["734454002082775040" ,"Web developer"],
"🌐" : ["734454060417024072" ,"Network Engineer"],
"👮" : ["734454093833175151" ,"Network Security "],
"🐧" : ["734454127551053924" ,"Linux Guru"]
};
const limits = {
1 : 1,
2 : 4,
3 : 6,
4 : 0,
5 : 0
}
client.on('messageReactionAdd', async (reaction, user) => {
if(reaction.message.id === role_message_id){
if (reaction.partial) {
try {
await reaction.fetch();
} catch (error) {
console.log('Something went wrong when fetching the message: ', error);
return;
}
}
let emoji = reaction.emoji.name;
let member = await reaction.message.guild.members.fetch(user.id);
try {
mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
let db = mongoose.connection;
db.once("open", async function callback () {
let user_data = await userModel.find({_id: user.id}, "profession rank")
let profession = user_data[0].profession
let rank = user_data[0].rank
if(limits[rank] < profession.length + 1 && limits[rank] !== 0){
user.send(`You cannot have more than ${limits[rank]} professions at this rank!`)
return;
}
profession.push(reaction_to_prof[emoji][1]);
member.roles.add( reaction_to_prof[emoji][0]);
userModel.findOneAndUpdate(
{_id: user.id},
{profession: profession},
{
new: true,
runValidators: true,
useFindAndModify: false
}, function(err, result) {
//if (err) {console.log(err); } else {console.log(result);}
});
user.send(`You now have the profession ${reaction_to_prof[emoji][1]}!`)
});
}catch (error) {
console.log(error)
console.log("ERROR WITH MONGODB CONNECTION");
}
}
});
client.on('messageReactionRemove', async (reaction, user) => {
if(reaction.message.id === role_message_id){
if (reaction.partial) {
try {
await reaction.fetch();
} catch (error) {
console.log('Something went wrong when fetching the message: ', error);
return;
}
}
let emoji = reaction.emoji.name;
let member = await reaction.message.guild.members.fetch(user.id);
try {
mongoose.connect( mongo_url, {useNewUrlParser: true, useUnifiedTopology: true}, () => null );
let db = mongoose.connection;
db.once("open", async function callback () {
let user_data = await userModel.find({_id: user.id}, "profession rank")
let profession = user_data[0].profession
let rank = user_data[0].rank
if(profession_index != -1){
profession.splice(profession_index, 1)
}
member.roles.remove(reaction_to_prof[emoji][0]);
userModel.findOneAndUpdate(
{_id: user.id},
{profession: profession},
{
new: true,
runValidators: true,
useFindAndModify: false
}, function(err, result) {
// if (err) {console.log(err); } else {console.log(result);}
});
});
user.send(`You now don't have the profession ${reaction_to_prof[emoji][1]}!`)
}catch (error) {
console.log(error)
console.log("ERROR WITH MONGODB CONNECTION");
}
}
});
// login to Discord with your app's token
client.login(token);

+ 815
- 0
xi_tracker/package-lock.json View File

@ -0,0 +1,815 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"@discordjs/collection": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.5.tgz",
"integrity": "sha512-CU1q0UXQUpFNzNB7gufgoisDHP7n+T3tkqTsp3MNUkVJ5+hS3BCvME8uCXAUFlz+6T2FbTCu75A+yQ7HMKqRKw=="
},
"@discordjs/form-data": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz",
"integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"requires": {
"event-target-shim": "^5.0.0"
}
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
},
"are-we-there-yet": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"requires": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"bl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz",
"integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
}
},
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"bson": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz",
"integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q=="
},
"canvas": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.6.1.tgz",
"integrity": "sha512-S98rKsPcuhfTcYbtF53UIJhcbgIAK533d1kJKMwsMwAIFgfd58MOyxRud3kktlzWiEkFliaJtvyZCBtud/XVEA==",
"requires": {
"nan": "^2.14.0",
"node-pre-gyp": "^0.11.0",
"simple-get": "^3.0.3"
}
},
"chownr": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
},
"decompress-response": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
"requires": {
"mimic-response": "^2.0.0"
}
},
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
},
"denque": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
},
"detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
},
"discord.js": {
"version": "12.2.0",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.2.0.tgz",
"integrity": "sha512-Ueb/0SOsxXyqwvwFYFe0msMrGqH1OMqpp2Dpbplnlr4MzcRrFWwsBM9gKNZXPVBHWUKiQkwU8AihXBXIvTTSvg==",
"requires": {
"@discordjs/collection": "^0.1.5",
"@discordjs/form-data": "^3.0.1",
"abort-controller": "^3.0.0",
"node-fetch": "^2.6.0",
"prism-media": "^1.2.0",
"setimmediate": "^1.0.5",
"tweetnacl": "^1.0.3",
"ws": "^7.2.1"
}
},
"event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
},
"fs-minipass": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
"integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
"requires": {
"minipass": "^2.6.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"requires": {
"aproba": "^1.0.3",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.0",
"object-assign": "^4.1.0",
"signal-exit": "^3.0.0",
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wide-align": "^1.1.0"
}
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ignore-walk": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
"integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
"requires": {
"minimatch": "^3.0.4"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"requires": {
"number-is-nan": "^1.0.0"
}
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"kareem": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz",
"integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw=="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
},
"mime-types": {
"version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"requires": {
"mime-db": "1.44.0"
}
},
"mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA=="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"minipass": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
}
},
"minizlib": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
"integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
"requires": {
"minipass": "^2.9.0"
}
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": {
"minimist": "^1.2.5"
}
},
"mongodb": {
"version": "3.5.9",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.9.tgz",
"integrity": "sha512-vXHBY1CsGYcEPoVWhwgxIBeWqP3dSu9RuRDsoLRPTITrcrgm1f0Ubu1xqF9ozMwv53agmEiZm0YGo+7WL3Nbug==",
"requires": {
"bl": "^2.2.0",
"bson": "^1.1.4",
"denque": "^1.4.1",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2",
"saslprep": "^1.0.0"
}
},
"mongoose": {
"version": "5.9.25",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.25.tgz",
"integrity": "sha512-vz/DqJ3mrHqEIlfRbKmDZ9TzQ1a0hCtSQpjHScIxr4rEtLs0tjsXDeEWcJ/vEEc3oLfP6vRx9V+uYSprXDUvFQ==",
"requires": {
"bson": "^1.1.4",
"kareem": "2.3.1",
"mongodb": "3.5.9",
"mongoose-legacy-pluralize": "1.0.2",
"mpath": "0.7.0",
"mquery": "3.2.2",
"ms": "2.1.2",
"regexp-clone": "1.0.0",
"safe-buffer": "5.2.1",
"sift": "7.0.1",
"sliced": "1.0.1"
},
"dependencies": {
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}
}
},
"mongoose-legacy-pluralize": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
"integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ=="
},
"mpath": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.7.0.tgz",
"integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg=="
},
"mquery": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz",
"integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==",
"requires": {
"bluebird": "3.5.1",
"debug": "3.1.0",
"regexp-clone": "^1.0.0",
"safe-buffer": "5.1.2",
"sliced": "1.0.1"
},
"dependencies": {
"bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"nan": {
"version": "2.14.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
"integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
},
"needle": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz",
"integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==",
"requires": {
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"sax": "^1.2.4"
}
},
"node-fetch": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
},
"node-pre-gyp": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz",
"integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==",
"requires": {
"detect-libc": "^1.0.2",
"mkdirp": "^0.5.1",
"needle": "^2.2.1",
"nopt": "^4.0.1",
"npm-packlist": "^1.1.6",
"npmlog": "^4.0.2",
"rc": "^1.2.7",
"rimraf": "^2.6.1",
"semver": "^5.3.0",
"tar": "^4"
}
},
"nopt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
"integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
"requires": {
"abbrev": "1",
"osenv": "^0.1.4"
}
},
"npm-bundled": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
"integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
"requires": {
"npm-normalize-package-bin": "^1.0.1"
}
},
"npm-normalize-package-bin": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
},
"npm-packlist": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
"integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
"requires": {
"ignore-walk": "^3.0.1",
"npm-bundled": "^1.0.1",
"npm-normalize-package-bin": "^1.0.1"
}
},
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"requires": {
"are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0",
"gauge": "~2.7.3",
"set-blocking": "~2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"osenv": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"requires": {
"os-homedir": "^1.0.0",
"os-tmpdir": "^1.0.0"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"prism-media": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.2.tgz",
"integrity": "sha512-I+nkWY212lJ500jLe4tN9tWO7nRiBAVdMv76P9kffZjYhw20raMlW1HSSvS+MLXC9MmbNZCazMrAr+5jEEgTuw=="
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"qs": {
"version": "6.9.4",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz",
"integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ=="
},
"rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"requires": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
}
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"regexp-clone": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
"integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
},
"require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"requires": {
"resolve-from": "^2.0.0",
"semver": "^5.1.0"
}
},
"resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
},
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"requires": {
"glob": "^7.1.3"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
},
"sift": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz",
"integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g=="
},
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
"simple-concat": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
"integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
},
"simple-get": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
"integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
"requires": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"sliced": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
"integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
},
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"requires": {
"memory-pager": "^1.0.2"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"tar": {
"version": "4.4.13",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
"integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
"minipass": "^2.8.6",
"minizlib": "^1.2.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
"yallist": "^3.0.3"
}
},
"trello-node-api": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/trello-node-api/-/trello-node-api-0.0.9.tgz",
"integrity": "sha512-UVkn8rZV427i1tnn/flIkbmIzblEv868poTeOHhMrsblP3ogA6umgy2dh6+1QvjTvBQ1YiVpVUQQp/ZSBZlOMA==",
"requires": {
"bluebird": "^3.7.2",
"debug": "^4.1.1",
"lodash.isplainobject": "^4.0.6",
"qs": "~6.9.1",
"safe-buffer": "^5.2.0"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}
}
},
"tweetnacl": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"requires": {
"string-width": "^1.0.2 || 2"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
}

Loading…
Cancel
Save