Added Query entries

- changed id to type ID!
- changed id to md5 hash of base64 string of properties
- added discord Id
- added paging to arrays
- implemented guildHandler into Guild query type
- added saved to retrieve saved songs/playlists
- added ready indicator boolean
- added querying logs
- added presences array
- added config as String
- added prefix
pull/33/head
Trivernis 6 years ago
parent 275179b990
commit 72794a2f63

@ -4,7 +4,6 @@ const Discord = require("discord.js"),
cmd = require("./lib/cmd"),
guilding = require('./lib/guilding'),
utils = require('./lib/utils'),
webapi = require('./lib/webapi'),
config = require('./config.json'),
args = require('args-parser')(process.argv),
sqlite3 = require('sqlite3'),
@ -12,6 +11,8 @@ const Discord = require("discord.js"),
prefix = args.prefix || config.prefix || '~',
gamepresence = args.game || config.presence;
let webapi = null;
class Bot {
constructor() {
this.client = new Discord.Client();
@ -44,11 +45,11 @@ class Bot {
}
}
guilding.setLogger(logger);
webapi.setLogger(logger);
cmd.init(prefix);
logger.verbose('Registering commands');
this.registerCommands();
logger.debug('Checking for ./data/ existence');
utils.dirExistence('./data', () => {
logger.verbose('Connecting to main database');
this.maindb = new sqlite3.Database('./data/main.db', (err) => {
@ -58,7 +59,7 @@ class Bot {
this.maindb.run(`${utils.sql.tableExistCreate} presences (
${utils.sql.pkIdSerial},
text VARCHAR(255) UNIQUE NOT NULL
)`, (err) => {
)`, (err) => {
if (err) {
logger.error(err.message);
} else {
@ -72,15 +73,27 @@ class Bot {
this.registerCallbacks();
if (config.webservice && config.webservice.enabled) {
logger.verbose('Importing webapi');
webapi = require('./lib/webapi');
webapi.setLogger(logger);
logger.verbose('Creating WebServer');
this.webServer = new webapi.WebServer(config.webservice.port || 8080);
logger.debug('Setting Reference Objects to webserver');
this.webServer.setReferenceObjects({
client: this.client
client: this.client,
presences: this.presences,
maind: this.maindb,
prefix: prefix,
getGuildHandler: (guild) => this.getGuildHandler(guild, prefix)
});
}
}
/**
* Starting the bot by connecting to the discord service and starting the webservice.
* @returns {Promise<any>}
*/
start() {
return new Promise((resolve, reject) => {
this.client.login(authToken).then(() => {
@ -89,7 +102,7 @@ class Bot {
}).catch((err) => {
reject(err);
});
if (this.webServer){
if (this.webServer) {
this.webServer.start();
logger.info(`WebServer runing on port ${this.webServer.port}`);
}
@ -116,7 +129,8 @@ class Bot {
});
this.presences.push(line);
});
this.rotator = this.client.setInterval(() => this.rotatePresence(), config.presence_duration || 360000);
this.rotator = this.client.setInterval(() => this.rotatePresence(),
config.presence_duration || 360000);
fs.unlink('./data/presences.txt', (err) => {
if (err)
logger.warn(err.message);
@ -140,7 +154,8 @@ class Bot {
this.presences.push(row.text);
}
}
this.rotator = this.client.setInterval(() => this.rotatePresence(), config.presence_duration || 360000);
this.rotator = this.client.setInterval(() => this.rotatePresence(),
config.presence_duration || 360000);
})
}
}
@ -219,8 +234,10 @@ class Bot {
rotatePresence() {
let pr = this.presences.shift();
this.presences.push(pr);
this.client.user.setPresence({game: {name: `${gamepresence} | ${pr}`, type: "PLAYING"}, status: 'online'});
logger.debug(`Presence rotation to ${pr}`);
this.client.user.setPresence({
game: {name: `${gamepresence} | ${pr}`, type: "PLAYING"},
status: 'online'
}).then(() => logger.debug(`Presence rotation to ${pr}`));
}
@ -234,7 +251,11 @@ class Bot {
this.client.on('ready', () => {
logger.info(`logged in as ${this.client.user.tag}!`);
this.client.user.setPresence({game: {name: gamepresence, type: "PLAYING"}, status: 'online'})
this.client.user.setPresence({
game: {
name: gamepresence, type: "PLAYING"
}, status: 'online'
})
.catch((err) => {
if (err)
logger.warn(err.message);

@ -1,39 +1,60 @@
type User {
id: String
name: String
id: ID!
discordId: String
name: String!
avatar: String
bot: Boolean
tag: String
tag: String!
}
type Role {
id: String
id: ID!
discordId: String
name: String
color: String
members: [GuildMember]
members(first: Int = 10, offset: Int = 0, id: String): [GuildMember]
}
type GuildMember {
id: String
id: ID!
discordId: String
user: User
nickname: String
roles: [Role]
roles(first: Int = 10, offset: Int = 0, id: String): [Role]
highestRole: Role
}
type Guild {
id: String
id: ID!
discordId: String
name: String
owner: GuildMember
members: [GuildMember]
roles: [Role]
members(first: Int = 10, offset: Int = 0, id: String): [GuildMember]
roles(first: Int = 10, offset: Int = 0, id: String): [Role]
memberCount: Int
icon: String
ready: Boolean
saved(first: Int = 10, offset: Int = 0, id: String, name: String): [SavedEntry!]
}
type Client {
guilds(count: Int): [Guild]
guilds(first: Int = 10, offset: Int = 0, id: String): [Guild]
user: User
ping: Float
status: Int
uptime: Int
}
type SavedEntry {
id: ID!
url: String!
name: String!
}
type LogEntry {
id: ID!
message: String
level: String
timestamp: String
}
type Query {
client: Client
presences: [String]!
config: String
prefix: String
logs(first: Int, offset: Int = 0, id: String, last: Int = 10): [LogEntry]
}

@ -11,37 +11,38 @@ const winston = require('winston'),
loggingFullFormat = winston.format.combine(
winston.format.splat(),
winston.format.timestamp({
format: 'MM-DD HH:mm:ss.SSS' // don't include the year because the filename already tells
format: 'YY-MM-DD HH:mm:ss.SSS'
}),
fileLoggingFormat // the logging format for files that logs with a capitalized level
winston.format.json()
),
logger = winston.createLogger({
level: winston.config.npm.levels, // logs with npm levels
format: loggingFullFormat, // the full format for files
format: loggingFullFormat,
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(), // colorizes the console logging output
winston.format.colorize(),
winston.format.splat(),
winston.format.timestamp({
format: 'YY-MM-DD HH:mm:ss.SSS' // logs with the year to the console
format: 'YY-MM-DD HH:mm:ss.SSS'
}),
consoleLoggingFormat // logs with the custom console format
consoleLoggingFormat
),
level: args.loglevel || 'info' // logs to the console with the arg loglevel or info if it is not given
level: args.loglevel || 'info'
}),
new winston.transports.File({
level: 'debug', // logs with debug level to the active file
filename: './.log/latest.log', // the filename of the current file,
level: 'debug',
filename: './.log/latest.log',
options: {flags: 'w'} // overwrites the file on restart
}),
new DailyRotateFile({
level: 'verbose', // log verbose in the rotating logvile
filename: './.log/%DATE%.log', // the pattern of the filename
datePattern: 'YYYY-MM-DD', // the pattern of %DATE%
zippedArchive: true, // indicates that old logfiles should get zipped
maxSize: '32m', // the maximum filesize
maxFiles: '30d' // the maximum files to keep
level: 'verbose',
filename: './.log/%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '32m',
maxFiles: '30d',
json: true
})
]
});

@ -1,6 +1,8 @@
const express = require('express'),
graphqlHTTP = require('express-graphql'),
{buildSchema} = require('graphql'),
compression = require('compression'),
md5 = require('js-md5'),
config = require('../config.json'),
fs = require('fs');
@ -18,7 +20,19 @@ exports.WebServer = class {
this.root = {};
}
/**
* Starting the api webserver
*/
start() {
this.app.use(compression({
filter: (req, res) => {
if (req.headers['x-no-compression']) {
return false
} else {
return compression.filter(req, res);
}
}
}));
this.app.use('/graphql', graphqlHTTP({
schema: this.schema,
rootValue: this.root,
@ -30,9 +44,17 @@ exports.WebServer = class {
setReferenceObjects(objects) {
this.root = {
client: {
guilds: ({count}) => {
guilds: (args) => {
let dcGuilds = objects.client.guilds.values();
return Array.from(dcGuilds).map((x) => new Guild(x)).slice(0, count);
if (args.id) {
return [Array.from(dcGuilds)
.map((x) => new Guild(x, objects.getGuildHandler(x)))
.find(x => (x.id === args.id))];
} else {
return Array.from(dcGuilds)
.map((x) => new Guild(x, objects.getGuildHandler(x)))
.slice(args.offset, args.offset + args.first);
}
},
user: () => {
return new User(objects.client.user);
@ -45,54 +67,180 @@ exports.WebServer = class {
},
uptime: () => {
return objects.client.uptime;
}
},
},
prefix: objects.prefix,
presences: objects.presences,
config: JSON.stringify(config),
logs: (args) => {
return new Promise((resolve) => {
let logEntries = [];
let lineReader = require('readline').createInterface({
input: require('fs').createReadStream('./.log/latest.log')
});
lineReader.on('line', (line) => {
logEntries.push(new LogEntry(JSON.parse(line)));
});
lineReader.on('close', () => {
if (args.id) {
resolve([logEntries.find(x => (x.id === args.id))]);
} else if (args.first) {
resolve(logEntries.slice(args.offset, args.offset + args.first));
} else {
resolve(logEntries.slice(logEntries.length - args.last));
}
})
})
}
}
}
};
function generateID(valArr) {
let b64 = Buffer.from(valArr.map(x => {
if (x)
return x.toString();
else
return 'null';
}).join('_')).toString('base64');
return md5(b64);
}
class Guild {
constructor(discordGuild) {
this.id = discordGuild.id;
constructor(discordGuild, guildHandler) {
this.id = generateID(['Guild', discordGuild.id]);
this.discordId = discordGuild.id;
this.name = discordGuild.name;
this.owner = new GuildMember(discordGuild.owner);
this.memberCount = discordGuild.memberCount;
this.icon = discordGuild.iconURL;
this.members = Array.from(discordGuild.members.values())
this.prMembers = Array.from(discordGuild.members.values())
.map((x) => new GuildMember(x));
this.roles = Array.from(discordGuild.roles.values())
this.prRoles = Array.from(discordGuild.roles.values())
.map((x) => new Role(x));
guildHandler = guildHandler || {};
this.ready = guildHandler.ready;
this.prSaved = null;
this.guildHandler = guildHandler;
}
querySaved() {
return new Promise((resolve) => {
if (this.guildHandler.db) {
let saved = [];
this.guildHandler.db.all('SELECT * FROM playlists', (err, rows) => {
if (err) {
logger.error(err.message);
resolve(null)
} else {
for (let row of rows) {
saved.push({
id: generateID(['Guild', 'ROW', row.id, row.name]),
name: row.name,
url: row.url
});
}
resolve(saved);
}
})
} else {
resolve(null);
}
});
}
saved(args) {
return new Promise((resolve) => {
this.querySaved().then((result) => {
if (result) {
if (args.id) {
resolve([result.find(x => (x.id === args.id))]);
} else if (args.name) {
resolve([result.find(x => (x.name === args.name))]);
} else {
resolve(result.slice(args.offset, args.offset + args.first));
}
} else {
resolve(null);
}
})
})
}
roles(args) {
if (args.id) {
return [this.prRoles.find(x => (x.id === args.id))];
} else {
return this.prRoles.slice(args.offset, args.offset + args.first);
}
}
members(args) {
if (args.id) {
return [this.prMembers.find(x => (x.id === args.id))];
} else {
return this.prMembers.slice(args.offset, args.offset + args.first);
}
}
}
class Role {
constructor(discordRole) {
this.id = discordRole.id;
this.id = generateID(['Role', discordRole.id]);
this.discordId = discordRole.id;
this.name = discordRole.name;
this.color = discordRole.hexColor;
this.members = Array.from(discordRole.members.values)
this.prMembers = Array.from(discordRole.members.values)
.map((x) => new GuildMember(x));
}
members(args) {
if (args.id) {
return [this.prMembers.find(x => (x.id === args.id))];
} else {
return this.prMembers.slice(args.offset, args.offset + args.first);
}
}
}
class GuildMember {
constructor(discordGuildMember) {
this.id = discordGuildMember.id;
this.id = generateID(['GuildMember', discordGuildMember.id]);
this.discordId = discordGuildMember.id;
this.user = new User(discordGuildMember.user);
this.nickname = discordGuildMember.nickname;
this.roles = Array.from(discordGuildMember.roles.values())
this.prRoles = Array.from(discordGuildMember.roles.values())
.map((x) => new Role(x));
this.highestRole = new Role(discordGuildMember.highestRole);
}
roles(args) {
if (args.id) {
return [this.prRoles.find(x => (x.id === args.id))];
} else {
return this.prRoles.slice(args.offset, args.offset + args.first);
}
}
}
class User {
constructor(discordUser) {
this.id = discordUser.id;
this.id = generateID(['User', discordUser.id]);
this.discordId = discordUser.id;
this.name = discordUser.username;
this.avatar = discordUser.avatarURL;
this.bot = discordUser.bot;
this.tag = discordUser.tag;
this.tag = discordUser.tag;
}
}
class LogEntry {
constructor(entry) {
this.id = generateID(['LogEntry', entry.level, entry.timestamp]);
this.message = entry.message;
this.timestamp = entry.timestamp;
this.level = entry.level;
}
}

@ -8,6 +8,7 @@
},
"dependencies": {
"args-parser": "1.1.0",
"compression": "^1.7.3",
"discord.js": "11.4.2",
"eslint-plugin-graphql": "^3.0.1",
"express": "^4.16.4",
@ -15,6 +16,7 @@
"ffmpeg-binaries": "4.0.0",
"get-youtube-title": "1.0.0",
"graphql": "^14.1.1",
"js-md5": "^0.7.3",
"opusscript": "0.0.6",
"sqlite3": "4.0.6",
"winston": "3.2.1",

Loading…
Cancel
Save