mirror of
https://github.com/LBRYFoundation/curate.git
synced 2025-08-23 17:37:25 +00:00
Compare commits
No commits in common. "master" and "0.1" have entirely different histories.
32 changed files with 1187 additions and 1752 deletions
10
.github/workflows/eslint.yml
vendored
10
.github/workflows/eslint.yml
vendored
|
@ -12,11 +12,11 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Node v18
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Node v12
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 12.x
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn
|
||||
- name: Install dependencies
|
||||
|
@ -24,7 +24,7 @@ jobs:
|
|||
- name: Run ESLint
|
||||
run: yarn run eslint:fix
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@v9
|
||||
uses: EndBug/add-and-commit@v4
|
||||
with:
|
||||
add: src
|
||||
message: "chore(lint): Auto-fix linting errors"
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,5 +3,4 @@ config/default.js
|
|||
config/production.js
|
||||
config/curate.sqlite
|
||||
package-lock.json
|
||||
.idea/
|
||||
yarn-error.log
|
||||
.idea/
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"deepscan.enable": true
|
||||
}
|
|
@ -7,7 +7,7 @@ This bot allows the community of LBRY to support eachother through the [LBRY Fou
|
|||
|
||||
## Installation
|
||||
* Pull the repo
|
||||
* Install [Node.JS LTS](https://nodejs.org/) (Currently Node v18.x)
|
||||
* Install [Node.JS LTS](https://nodejs.org/) (Currently Node v12.x)
|
||||
* Install [Yarn](https://yarnpkg.com/) (`npm install yarn -g`)
|
||||
* Install [Redis](https://redis.io/) ([quickstart](https://redis.io/topics/quickstart))
|
||||
* Install LBRY-SDK
|
||||
|
@ -19,7 +19,7 @@ This bot allows the community of LBRY to support eachother through the [LBRY Fou
|
|||
This bot would not be possible without the following people/software:
|
||||
|
||||
* LBRY Inc. and the LBRY SDK
|
||||
* Dysnomia - NodeJS Library for Discord, fork of Eris
|
||||
* Eris - NodeJS Library for Discord
|
||||
* LBRY Foundation
|
||||
* Snazzah - Creator of the Faux command base and developer of the bot
|
||||
* Coolguy3289 - Developer of the bot and command flow
|
||||
|
|
|
@ -11,42 +11,34 @@ module.exports = {
|
|||
debug: false,
|
||||
// [number] The main embed color (#ffffff -> 0xffffff)
|
||||
embedColor: 0x15521c,
|
||||
// [string|Array<string>] The role ID(s) for curator roles
|
||||
// [string] curator_role_id
|
||||
curatorRoleID: "",
|
||||
// [string|Array<string>] The role ID(s) for trusted roles
|
||||
trustedRoleID: "",
|
||||
// [string|Array<string>] The role ID(s) for admin roles
|
||||
// [string] admin_role_id
|
||||
adminRoleID: "",
|
||||
// [string] guild_id
|
||||
guildID: "",
|
||||
// [string] sdk_url
|
||||
sdkURL: "",
|
||||
// [string] The ABSOLUTE path to the main wallet file to back up
|
||||
walletPath: "~/.lbryum/wallets/default_wallet",
|
||||
// [string] The ABSOLUTE path folder to store wallet backups after every deletion
|
||||
walletBackupFolder: "~/.lbryum_backup/",
|
||||
// [string] Amount to auto-fund upon account creation
|
||||
startingBalance: "",
|
||||
// [Object] Dysnomia client options (subset of https://abal.moe/Eris/docs/Client)
|
||||
// [Object] Eris client options (https://abal.moe/Eris/docs/Client)
|
||||
discordConfig: {
|
||||
autoreconnect: true,
|
||||
allowedMentions: {
|
||||
everyone: false,
|
||||
roles: false,
|
||||
users: true
|
||||
},
|
||||
maxShards: "auto",
|
||||
messageLimit: 0,
|
||||
gateway: {
|
||||
autoreconnect: true,
|
||||
maxShards: "auto",
|
||||
intents: [
|
||||
"guilds",
|
||||
"guildMessages",
|
||||
"guildMessageReactions",
|
||||
"directMessages",
|
||||
"directMessageReactions",
|
||||
"messageContent"
|
||||
]
|
||||
}
|
||||
intents: [
|
||||
"guilds",
|
||||
"guildEmojis",
|
||||
"guildMessages",
|
||||
"guildMessageReactions",
|
||||
"directMessages",
|
||||
"directMessageReactions"
|
||||
]
|
||||
},
|
||||
// [Object] Redis config
|
||||
redis: {
|
||||
|
|
23
package.json
23
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "lbry-curate",
|
||||
"version": "0.1.1",
|
||||
"version": "0.0.1",
|
||||
"description": "Support the LBRY Community through Discord!",
|
||||
"main": "src/bot.js",
|
||||
"scripts": {
|
||||
|
@ -9,20 +9,21 @@
|
|||
"eslint:fix": "eslint ./src --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@projectdysnomia/dysnomia": "github:projectdysnomia/dysnomia#0df1369a822dba8851c667b22d5bac34f4e849e6",
|
||||
"cat-loggr": "^1.2.2",
|
||||
"config": "^3.3.9",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"abort-controller": "^3.0.0",
|
||||
"cat-loggr": "^1.1.0",
|
||||
"config": "^3.3.1",
|
||||
"eris": "^0.13.3",
|
||||
"eventemitter3": "^4.0.4",
|
||||
"fuzzy": "^0.1.3",
|
||||
"ioredis": "^5.3.2",
|
||||
"just-clone": "^6.2.0",
|
||||
"moment": "^2.30.1",
|
||||
"moment": "^2.27.0",
|
||||
"node-fetch": "^2.3.0",
|
||||
"redis": "^3.0.2",
|
||||
"require-reload": "^0.2.2",
|
||||
"sequelize": "^6.35.2",
|
||||
"sqlite3": "^5.1.7"
|
||||
"sequelize": "^6.3.4",
|
||||
"sqlite3": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.56.0"
|
||||
"eslint": "^7.6.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
19
src/bot.js
19
src/bot.js
|
@ -1,4 +1,4 @@
|
|||
const Dysnomia = require('@projectdysnomia/dysnomia');
|
||||
const Eris = require('eris');
|
||||
const Database = require('./database');
|
||||
const EventHandler = require('./events');
|
||||
const CommandLoader = require('./commandloader');
|
||||
|
@ -8,13 +8,12 @@ const path = require('path');
|
|||
const CatLoggr = require('cat-loggr');
|
||||
const config = require('config');
|
||||
const LBRY = require('./structures/LBRY');
|
||||
const clone = require('just-clone');
|
||||
|
||||
class CurateBot extends Dysnomia.Client {
|
||||
class CurateBot extends Eris.Client {
|
||||
constructor({ packagePath, mainDir } = {}) {
|
||||
// Initialization
|
||||
const pkg = require(packagePath || `${mainDir}/package.json`);
|
||||
super(`Bot ${config.token}`, clone(config.discordConfig));
|
||||
super(config.token, JSON.parse(JSON.stringify(config.discordConfig)));
|
||||
this.dir = mainDir;
|
||||
this.pkg = pkg;
|
||||
this.logger = new CatLoggr({
|
||||
|
@ -24,8 +23,10 @@ class CurateBot extends Dysnomia.Client {
|
|||
{ name: 'error', color: CatLoggr._chalk.black.bgRed, err: true },
|
||||
{ name: 'warn', color: CatLoggr._chalk.black.bgYellow, err: true },
|
||||
{ name: 'init', color: CatLoggr._chalk.black.bgGreen },
|
||||
{ name: 'webserv', color: CatLoggr._chalk.black.bgBlue },
|
||||
{ name: 'info', color: CatLoggr._chalk.black.bgCyan },
|
||||
{ name: 'assert', color: CatLoggr._chalk.cyan.bgBlack },
|
||||
{ name: 'poster', color: CatLoggr._chalk.yellow.bgBlack },
|
||||
{ name: 'debug', color: CatLoggr._chalk.magenta.bgBlack, aliases: ['log', 'dir'] },
|
||||
{ name: 'limiter', color: CatLoggr._chalk.gray.bgBlack },
|
||||
{ name: 'fileload', color: CatLoggr._chalk.white.bgBlack }
|
||||
|
@ -102,17 +103,17 @@ class CurateBot extends Dysnomia.Client {
|
|||
}
|
||||
|
||||
/**
|
||||
* Kills the bot
|
||||
* KIlls the bot
|
||||
*/
|
||||
dieGracefully() {
|
||||
return super.disconnect(false);
|
||||
return super.disconnect();
|
||||
}
|
||||
|
||||
// Typing
|
||||
|
||||
/**
|
||||
* Start typing in a channel
|
||||
* @param {Dysnomia.TextableChannel} channel The channel to start typing in
|
||||
* @param {Channel} channel The channel to start typing in
|
||||
*/
|
||||
async startTyping(channel) {
|
||||
if (this.isTyping(channel)) return;
|
||||
|
@ -124,7 +125,7 @@ class CurateBot extends Dysnomia.Client {
|
|||
|
||||
/**
|
||||
* Whether the bot is currently typing in a channel
|
||||
* @param {Dysnomia.TextableChannel} channel
|
||||
* @param {Channel} channel
|
||||
*/
|
||||
isTyping(channel) {
|
||||
return this.typingIntervals.has(channel.id);
|
||||
|
@ -132,7 +133,7 @@ class CurateBot extends Dysnomia.Client {
|
|||
|
||||
/**
|
||||
* Stops typing in a channel
|
||||
* @param {Dysnomia.TextableChannel} channel
|
||||
* @param {Channel} channel
|
||||
*/
|
||||
stopTyping(channel) {
|
||||
if (!this.isTyping(channel)) return;
|
||||
|
|
|
@ -37,7 +37,6 @@ module.exports = class AbaondonAll extends Command {
|
|||
header: 'Are you sure you want to abandon **all supports** from **all accounts**?'
|
||||
})) return;
|
||||
await this.client.startTyping(message.channel);
|
||||
await Util.LBRY.syncPairs(this.client);
|
||||
const pairs = await this.client.sqlite.getAll();
|
||||
let count = 0;
|
||||
for (let i = 0, len = pairs.length; i < len; i++) {
|
||||
|
@ -51,7 +50,7 @@ module.exports = class AbaondonAll extends Command {
|
|||
}
|
||||
|
||||
get metadata() { return {
|
||||
category: 'Admin',
|
||||
category: 'Curator',
|
||||
description: 'Abandons all supports of the bot or of a given account.',
|
||||
usage: '[id|@mention]'
|
||||
}; }
|
||||
|
|
|
@ -13,12 +13,12 @@ module.exports = class AdminBalance extends Command {
|
|||
const response = await this.client.lbry.walletBalance();
|
||||
const wallet = await response.json();
|
||||
if (await this.handleResponse(message, response, wallet)) return;
|
||||
return message.channel.createMessage({ embeds: [{
|
||||
return message.channel.createMessage({ embed: {
|
||||
color: config.embedColor,
|
||||
description: `**Available:** ${wallet.result.available} LBC\n\n` +
|
||||
`Reserved in Supports: ${wallet.result.reserved_subtotals.supports} LBC\n` +
|
||||
`Total: ${wallet.result.total} LBC`
|
||||
}] });
|
||||
} });
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
const GenericPager = require('../../structures/GenericPager');
|
||||
|
||||
module.exports = class AllSupports extends Command {
|
||||
get name() { return 'allsupports'; }
|
||||
|
||||
get _options() { return {
|
||||
aliases: ['asups', 'allsups'],
|
||||
permissions: ['admin'],
|
||||
minimumArgs: 0
|
||||
}; }
|
||||
|
||||
async exec(message, { args }) {
|
||||
let givenClaim;
|
||||
if (args[0]) {
|
||||
givenClaim = Util.resolveToClaimID(args[0]);
|
||||
if (!givenClaim)
|
||||
// @TODO use claim_search for invalid claim ids
|
||||
return message.channel.createMessage('That Claim ID isn\'t valid.');
|
||||
}
|
||||
|
||||
await Util.LBRY.syncPairs(this.client);
|
||||
const pairs = await this.client.sqlite.getAll();
|
||||
if (pairs.length <= 0)
|
||||
return message.channel.createMessage('No users found in the database.');
|
||||
|
||||
const allSupports = [];
|
||||
|
||||
for (const pair of pairs) {
|
||||
const supportsCount = await Util.LBRY.getSupportsCount(this.client, pair.lbryID);
|
||||
if (supportsCount <= 0) continue;
|
||||
const supportsResponse = await this.client.lbry.listSupports({
|
||||
accountID: pair.lbryID, page_size: supportsCount, claimID: givenClaim });
|
||||
const supports = (await supportsResponse.json()).result.items;
|
||||
for (const support of supports)
|
||||
allSupports.push({
|
||||
...support,
|
||||
pair
|
||||
});
|
||||
}
|
||||
|
||||
if (allSupports.length <= 0)
|
||||
return message.channel.createMessage('No supports found.');
|
||||
|
||||
const paginator = new GenericPager(this.client, message, {
|
||||
items: allSupports,
|
||||
header: `All supports${
|
||||
givenClaim ? ` on claim \`${givenClaim}\`` : ''}`, itemTitle: 'Supports',itemsPerPage: 5,
|
||||
display: item => `> ${item.name} \`${item.claim_id}\`\n> <@${item.pair.discordID}> ${item.amount} LBC\n`
|
||||
});
|
||||
return paginator.start(message.channel.id, message.author.id);
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
category: 'Admin',
|
||||
description: 'List all supports from all users.',
|
||||
usage: '[claimID]'
|
||||
}; }
|
||||
};
|
|
@ -21,15 +21,8 @@ module.exports = class DeleteAccount extends Command {
|
|||
header:
|
||||
`Are you sure you want to delete that account? *(${supportsCount.toLocaleString()} support[s])*`
|
||||
})) return;
|
||||
try {
|
||||
await Util.LBRY.deleteAccount(this.client, discordID, account.accountID);
|
||||
return message.channel.createMessage('Deleted account.');
|
||||
} catch (e) {
|
||||
return message.channel.createMessage(
|
||||
'Failed to delete the account. An error most likely occured while backing up the wallet.' +
|
||||
`\n\`\`\`\n${e.toString()}\`\`\``
|
||||
);
|
||||
}
|
||||
await Util.LBRY.deleteAccount(this.client, discordID, account.accountID);
|
||||
return message.channel.createMessage('Deleted account.');
|
||||
} else
|
||||
return message.channel.createMessage('That user does not have an account.');
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
|
||||
module.exports = class DeleteAll extends Command {
|
||||
get name() { return 'deleteall'; }
|
||||
|
||||
get _options() { return {
|
||||
aliases: ['delall'],
|
||||
permissions: ['admin'],
|
||||
minimumArgs: 0
|
||||
}; }
|
||||
|
||||
async exec(message) {
|
||||
await Util.LBRY.syncPairs(this.client);
|
||||
const pairs = await this.client.sqlite.getAll();
|
||||
|
||||
if (!await this.client.messageAwaiter.confirm(message, {
|
||||
header:
|
||||
`Are you sure you want to delete **all** ${pairs.length} accounts?`
|
||||
})) return;
|
||||
|
||||
for (const pair of pairs) {
|
||||
try {
|
||||
await Util.LBRY.deleteAccount(this.client, pair.discordID, pair.lbryID);
|
||||
} catch (e) {
|
||||
return message.channel.createMessage(
|
||||
'Failed to delete an account. An error most likely occured while backing up the wallet.' +
|
||||
`\n\`\`\`\n${e.toString()}\`\`\``
|
||||
);
|
||||
}
|
||||
}
|
||||
return message.channel.createMessage('Deleted all accounts.');
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
category: 'Admin',
|
||||
description: 'Deletes all accounts in the database.'
|
||||
}; }
|
||||
};
|
|
@ -1,5 +1,4 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
|
||||
module.exports = class Deposit extends Command {
|
||||
get name() { return 'deposit'; }
|
||||
|
@ -10,8 +9,7 @@ module.exports = class Deposit extends Command {
|
|||
}; }
|
||||
|
||||
async exec(message) {
|
||||
const account = await Util.LBRY.findSDKAccount(this.client, account => account.is_default);
|
||||
const response = await this.client.lbry.listAddresses({ account_id: account.id });
|
||||
const response = await this.client.lbry.listAddresses();
|
||||
const address = await response.json();
|
||||
if (await this.handleResponse(message, response, address)) return;
|
||||
return message.channel.createMessage(`Address: ${address.result.items[0].address}`);
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
const config = require('config');
|
||||
|
||||
module.exports = class FundAll extends Command {
|
||||
get name() { return 'fundall'; }
|
||||
|
||||
get _options() { return {
|
||||
permissions: ['admin'],
|
||||
minimumArgs: 1
|
||||
}; }
|
||||
|
||||
async exec(message, { args }) {
|
||||
const givenAmount = Util.LBRY.ensureDecimal(args[0]);
|
||||
if (!givenAmount)
|
||||
return message.channel.createMessage('The second argument must be a numeric amount of LBC to send!');
|
||||
|
||||
await Util.LBRY.syncPairs(this.client);
|
||||
const pairs = await this.client.sqlite.getAll();
|
||||
if (pairs.length <= 0) {
|
||||
await this.client.startTyping(message.channel);
|
||||
const curatorRoles = Array.isArray(config.curatorRoleID)
|
||||
? config.curatorRoleID : [config.curatorRoleID];
|
||||
const members = await this.client.guilds.get(config.guildID).fetchMembers();
|
||||
for (const member of members) {
|
||||
if (curatorRoles.map(r => member.roles.includes(r)).includes(true)) {
|
||||
const account = await Util.LBRY.findOrCreateAccount(this.client, member.id);
|
||||
pairs.push({ discordID: member.id, lbryID: account.accountID });
|
||||
}
|
||||
}
|
||||
await Util.halt(5000);
|
||||
this.client.stopTyping(message.channel);
|
||||
}
|
||||
|
||||
if (!await this.client.messageAwaiter.confirm(message, {
|
||||
header: `Are you sure you want to fund **all** accounts? *(${givenAmount} LBC)*`
|
||||
})) return;
|
||||
|
||||
await this.client.startTyping(message.channel);
|
||||
const resultLines = [];
|
||||
let funded = 0,
|
||||
errored = 0;
|
||||
for (const pair of pairs) {
|
||||
const response = await this.client.lbry.fundAccount({ to: pair.lbryID, amount: givenAmount });
|
||||
await Util.halt(2000);
|
||||
const transaction = await response.json();
|
||||
if ('code' in transaction) {
|
||||
console.info('Failed to fund account', pair.lbryID, transaction.code, transaction.message);
|
||||
resultLines.push(`${pair.discordID} ! ${transaction.code} - ${transaction.message}`);
|
||||
errored++;
|
||||
} else {
|
||||
console.info('Funded account', pair.lbryID, transaction.result.txid);
|
||||
resultLines.push(`${pair.discordID} - https://explorer.lbry.com/tx/${transaction.result.txid}`);
|
||||
funded++;
|
||||
}
|
||||
await Util.halt(2000);
|
||||
}
|
||||
this.client.stopTyping(message.channel);
|
||||
return message.channel.createMessage(errored
|
||||
? `Failed to fund ${errored} accounts! (${funded} funded)`
|
||||
: `Successfully funded ${funded} account(s)!`, {
|
||||
name: 'result.txt',
|
||||
file: Buffer.from(resultLines.join('\n'), 'utf8')
|
||||
});
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
category: 'Admin',
|
||||
description: 'Funds all users in the database a specified amount of LBC.',
|
||||
usage: '<amount>'
|
||||
}; }
|
||||
};
|
|
@ -1,49 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const GenericPager = require('../../structures/GenericPager');
|
||||
|
||||
module.exports = class ListAll extends Command {
|
||||
get name() { return 'listall'; }
|
||||
get _options() { return {
|
||||
permissions: ['admin'],
|
||||
minimumArgs: 0
|
||||
}; }
|
||||
async exec(message, { args }) {
|
||||
const pairs = await this.client.sqlite.getAll();
|
||||
if (pairs.length <= 0)
|
||||
return message.channel.createMessage('No users found in the database.');
|
||||
|
||||
for (const pair of pairs) {
|
||||
const response = await this.client.lbry.accountBalance(pair.lbryID);
|
||||
const wallet = await response.json();
|
||||
if (!wallet.code) {
|
||||
pair.wallet_available = wallet.result.available;
|
||||
pair.wallet_reserve = wallet.result.reserved_subtotals.supports;
|
||||
pair.wallet_ok = true;
|
||||
} else {
|
||||
console.error([
|
||||
'There was an error while retrieving the balance of an account.',
|
||||
'This was likely caused by an old version of the Bot\'s SQLite database file. ' +
|
||||
'Run the sync command to avoid this error!'
|
||||
].join('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
const paginator = new GenericPager(this.client, message, {
|
||||
items: pairs, itemTitle: 'Users', itemsPerPage: 5,
|
||||
display: pair => `> <@${pair.discordID}> - \`${pair.lbryID}\`\n` +
|
||||
`> ${pair.wallet_ok
|
||||
? `${pair.wallet_available} available, ${pair.wallet_reserve} staked.`
|
||||
: 'Wallet Unavailable'}\n`
|
||||
});
|
||||
|
||||
if (args[0])
|
||||
paginator.toPage(args[0]);
|
||||
|
||||
return paginator.start(message.channel.id, message.author.id);
|
||||
}
|
||||
get metadata() { return {
|
||||
category: 'Admin',
|
||||
description: 'List all users in the database.',
|
||||
usage: '[page]'
|
||||
}; }
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
|
||||
module.exports = class Sync extends Command {
|
||||
get name() { return 'sync'; }
|
||||
|
||||
get _options() { return {
|
||||
permissions: ['admin']
|
||||
}; }
|
||||
|
||||
async exec(message) {
|
||||
const synced = await Util.LBRY.syncPairs(this.client);
|
||||
return message.channel.createMessage(`Synced ${synced} new pairs.`);
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
category: 'Admin',
|
||||
description: 'Sync SDK-Discord pairs.'
|
||||
}; }
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
|
||||
module.exports = class Abandon extends Command {
|
||||
module.exports = class Abaondon extends Command {
|
||||
get name() { return 'abandon'; }
|
||||
|
||||
get _options() { return {
|
||||
|
@ -11,8 +11,8 @@ module.exports = class Abandon extends Command {
|
|||
}; }
|
||||
|
||||
async exec(message, { args }) {
|
||||
const givenClaim = Util.resolveToClaimID(args[0]);
|
||||
if (!givenClaim)
|
||||
const givenClaim = args[0];
|
||||
if (!/^[a-f0-9]{40}$/.test(givenClaim))
|
||||
// @TODO use claim_search for invalid claim ids
|
||||
return message.channel.createMessage('That Claim ID isn\'t valid.');
|
||||
|
||||
|
|
|
@ -10,46 +10,19 @@ module.exports = class Balance extends Command {
|
|||
permissions: ['curatorOrAdmin']
|
||||
}; }
|
||||
|
||||
async exec(message, { args }) {
|
||||
if (args.length) {
|
||||
if (!Util.CommandPermissions.admin(this.client, message)) {
|
||||
const admins = (Array.isArray(config.adminRoleID) ? config.adminRoleID : [config.adminRoleID])
|
||||
.map(id => `"${this.client.guilds.get(config.guildID).roles.get(id).name}"`);
|
||||
return message.channel.createMessage(
|
||||
`You need to have the ${admins.join('/')} role(s) to see others balances!`);
|
||||
}
|
||||
|
||||
const discordID = Util.resolveToUserID(args[0]);
|
||||
if (!discordID)
|
||||
return message.channel.createMessage('That Discord user isn\'t valid.');
|
||||
|
||||
const account = await Util.LBRY.findOrCreateAccount(this.client, discordID, false);
|
||||
if (!account.accountID)
|
||||
return message.channel.createMessage('That Discord user does not have an account.');
|
||||
|
||||
const response = await this.client.lbry.accountBalance(account.accountID);
|
||||
const wallet = await response.json();
|
||||
if (await this.handleResponse(message, response, wallet)) return;
|
||||
return message.channel.createMessage({ embeds: [{
|
||||
color: config.embedColor,
|
||||
description: `<@${discordID}> has **${wallet.result.available}** LBC available.\n\n` +
|
||||
`Reserved in Supports: ${wallet.result.reserved_subtotals.supports} LBC\n` +
|
||||
`Total: ${wallet.result.total} LBC`
|
||||
}] });
|
||||
} else {
|
||||
const account = await Util.LBRY.findOrCreateAccount(this.client, message.author.id);
|
||||
const response = await this.client.lbry.accountBalance(account.accountID);
|
||||
const wallet = await response.json();
|
||||
if (await this.handleResponse(message, response, wallet)) return;
|
||||
return message.channel.createMessage({ embeds: [{
|
||||
color: config.embedColor,
|
||||
description: `You have **${wallet.result.available}** LBC available.\n\n` +
|
||||
`Reserved in Supports: ${wallet.result.reserved_subtotals.supports} LBC\n` +
|
||||
`Total: ${wallet.result.total} LBC` +
|
||||
(account.newAccount ? '\n\n:warning: This account was just created. ' +
|
||||
'Please wait a few seconds, and run the command again to get an accurate balance.' : '')
|
||||
}] });
|
||||
}
|
||||
async exec(message) {
|
||||
const account = await Util.LBRY.findOrCreateAccount(this.client, message.author.id);
|
||||
const response = await this.client.lbry.accountBalance(account.accountID);
|
||||
const wallet = await response.json();
|
||||
if (await this.handleResponse(message, response, wallet)) return;
|
||||
return message.channel.createMessage({ embed: {
|
||||
color: config.embedColor,
|
||||
description: `You have **${wallet.result.available}** LBC available.\n\n` +
|
||||
`Reserved in Supports: ${wallet.result.reserved_subtotals.supports} LBC\n` +
|
||||
`Total: ${wallet.result.total} LBC` +
|
||||
(account.newAccount ? '\n\n:warning: This account was just created. ' +
|
||||
'Please wait a few seconds, and run the command again to get an accurate balance.' : '')
|
||||
} });
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
|
|
|
@ -15,8 +15,8 @@ module.exports = class Support extends Command {
|
|||
if (!givenAmount)
|
||||
return message.channel.createMessage('The second argument must be a numeric amount of LBC to send!');
|
||||
|
||||
const givenClaim = Util.resolveToClaimID(args[0]);
|
||||
if (!givenClaim)
|
||||
const givenClaim = args[0];
|
||||
if (!/^[a-f0-9]{40}$/.test(givenClaim))
|
||||
// @TODO use claim_search for invalid claim ids
|
||||
return message.channel.createMessage('That Claim ID isn\'t valid.');
|
||||
|
||||
|
|
|
@ -42,14 +42,12 @@ module.exports = class Supports extends Command {
|
|||
const supportsResponse = await this.client.lbry.listSupports({
|
||||
accountID: account.accountID, page_size: supportsCount, claimID: givenClaim });
|
||||
console.debug(
|
||||
`Displaying supports for ${
|
||||
account.accountID}${givenClaim ? ` and claimID ${givenClaim}` : ''}, (${supportsCount})`);
|
||||
`Displaying supports for ${account.accountID}${givenClaim ? ` and claimID ${givenClaim}` : ''}, (${supportsCount})`);
|
||||
const supports = (await supportsResponse.json()).result.items;
|
||||
const paginator = new GenericPager(this.client, message, {
|
||||
items: supports,
|
||||
header: `All supports for <@${discordID || message.author.id}>${
|
||||
givenClaim ? ` on claim \`${givenClaim}\`` : ''}`, itemTitle: 'Supports',itemsPerPage: 5,
|
||||
display: item => `> ${item.name} \`${item.claim_id}\`\n> ${item.amount} LBC\n`
|
||||
header: `All supports for <@${discordID || message.author.id}>${givenClaim ? ` on claim \`${givenClaim}\`` : ''}`, itemTitle: 'Supports',
|
||||
display: item => `*lbry://**${item.name}***#\`${item.claim_id}\` (${item.amount} LBC)`
|
||||
});
|
||||
return paginator.start(message.channel.id, message.author.id);
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ module.exports = class Help extends Command {
|
|||
value: command.metadata.note
|
||||
});
|
||||
|
||||
return message.channel.createMessage({ embeds: [embed] });
|
||||
return message.channel.createMessage({ embed });
|
||||
}
|
||||
} else {
|
||||
// Display general help command
|
||||
|
@ -89,7 +89,7 @@ module.exports = class Help extends Command {
|
|||
inline: true
|
||||
});
|
||||
});
|
||||
return message.channel.createMessage({ embeds: [embed] });
|
||||
return message.channel.createMessage({ embed });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
|
||||
module.exports = class TAbandon extends Command {
|
||||
get name() { return 'tabandon'; }
|
||||
|
||||
get _options() { return {
|
||||
aliases: ['taban', 'tdrop'],
|
||||
permissions: ['trustedOrAdmin'],
|
||||
minimumArgs: 1
|
||||
}; }
|
||||
|
||||
async exec(message, { args }) {
|
||||
const givenClaim = Util.resolveToClaimID(args[0]);
|
||||
if (!givenClaim)
|
||||
// @TODO use claim_search for invalid claim ids
|
||||
return message.channel.createMessage('That Claim ID isn\'t valid.');
|
||||
|
||||
if (!await this.client.messageAwaiter.confirm(message, {
|
||||
header:
|
||||
'Are you sure you want to abandon a claim from a **trusted** account?'
|
||||
})) return;
|
||||
|
||||
const account = await Util.LBRY.findSDKAccount(this.client, account => account.is_default);
|
||||
|
||||
// Drop support
|
||||
const response = await this.client.lbry.abandonSupport({
|
||||
accountID: account.id, claimID: givenClaim });
|
||||
const transaction = await response.json();
|
||||
if (await this.handleResponse(message, response, transaction)) return;
|
||||
const txid = transaction.result.txid;
|
||||
return message.channel.createMessage(`Abandon successful! https://explorer.lbry.com/tx/${txid}`);
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
category: 'Trusted',
|
||||
description: 'Abandons a support on a given claim from the trusted account.',
|
||||
usage: '<claim>'
|
||||
}; }
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
const config = require('config');
|
||||
|
||||
module.exports = class TBalance extends Command {
|
||||
get name() { return 'tbalance'; }
|
||||
|
||||
get _options() { return {
|
||||
aliases: ['tbal', 'trustedbal', 'trustedbalance'],
|
||||
permissions: ['trustedOrAdmin']
|
||||
}; }
|
||||
|
||||
async exec(message) {
|
||||
const account = await Util.LBRY.findSDKAccount(this.client, account => account.is_default);
|
||||
const response = await this.client.lbry.accountBalance(account.id);
|
||||
const wallet = await response.json();
|
||||
if (await this.handleResponse(message, response, wallet)) return;
|
||||
return message.channel.createMessage({ embeds: [{
|
||||
color: config.embedColor,
|
||||
description: `**${wallet.result.available}** LBC is available in the trusted account.\n\n` +
|
||||
`Reserved in Supports: ${wallet.result.reserved_subtotals.supports} LBC\n` +
|
||||
`Total: ${wallet.result.total} LBC`
|
||||
}] });
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
category: 'Trusted',
|
||||
description: 'Shows the trusted wallet balance.'
|
||||
}; }
|
||||
};
|
|
@ -1,51 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const Util = require('../../util');
|
||||
|
||||
module.exports = class TSupport extends Command {
|
||||
get name() { return 'tsupport'; }
|
||||
|
||||
get _options() { return {
|
||||
aliases: ['tsup'],
|
||||
permissions: ['trustedOrAdmin'],
|
||||
minimumArgs: 2
|
||||
}; }
|
||||
|
||||
async exec(message, { args }) {
|
||||
const givenAmount = Util.LBRY.ensureDecimal(args[1]);
|
||||
if (!givenAmount)
|
||||
return message.channel.createMessage('The second argument must be a numeric amount of LBC to send!');
|
||||
|
||||
const givenClaim = Util.resolveToClaimID(args[0]);
|
||||
if (!givenClaim)
|
||||
// @TODO use claim_search for invalid claim ids
|
||||
return message.channel.createMessage('That Claim ID isn\'t valid.');
|
||||
|
||||
// Get and check balance
|
||||
const account = await Util.LBRY.findSDKAccount(this.client, account => account.is_default);
|
||||
const walletResponse = await this.client.lbry.accountBalance(account.id);
|
||||
const wallet = await walletResponse.json();
|
||||
if (await this.handleResponse(message, walletResponse, wallet)) return;
|
||||
const balance = wallet.result.available;
|
||||
if (parseFloat(givenAmount) > parseFloat(balance))
|
||||
return message.channel.createMessage('You don\'t have enough LBC to do this!');
|
||||
|
||||
if (!await this.client.messageAwaiter.confirm(message, {
|
||||
header:
|
||||
'Are you sure you want to support a claim from a **trusted** account?'
|
||||
})) return;
|
||||
|
||||
// Create support
|
||||
const response = await this.client.lbry.createSupport({
|
||||
accountID: account.id, claimID: givenClaim, amount: givenAmount });
|
||||
const transaction = await response.json();
|
||||
if (await this.handleResponse(message, response, transaction)) return;
|
||||
const txid = transaction.result.txid;
|
||||
return message.channel.createMessage(`Support successful! https://explorer.lbry.com/tx/${txid}`);
|
||||
}
|
||||
|
||||
get metadata() { return {
|
||||
category: 'Trusted',
|
||||
description: 'Support a given claim from the trusted account.',
|
||||
usage: '<claim> <amount>'
|
||||
}; }
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
const Command = require('../../structures/Command');
|
||||
const GenericPager = require('../../structures/GenericPager');
|
||||
const Util = require('../../util');
|
||||
|
||||
module.exports = class TSupports extends Command {
|
||||
get name() { return 'tsupports'; }
|
||||
get _options() { return {
|
||||
aliases: ['tsups'],
|
||||
permissions: ['trustedOrAdmin'],
|
||||
minimumArgs: 0
|
||||
}; }
|
||||
async exec(message, { args }) {
|
||||
let givenClaim;
|
||||
if (args[0]) {
|
||||
givenClaim = Util.resolveToClaimID(args[0]);
|
||||
if (!givenClaim)
|
||||
// @TODO use claim_search for invalid claim ids
|
||||
return message.channel.createMessage('That Claim ID isn\'t valid.');
|
||||
}
|
||||
|
||||
const account = await Util.LBRY.findSDKAccount(this.client, account => account.is_default);
|
||||
const supportsCount = await Util.LBRY.getSupportsCount(this.client, account.id);
|
||||
if (supportsCount <= 0)
|
||||
return message.channel.createMessage('No supports found.');
|
||||
|
||||
const supportsResponse = await this.client.lbry.listSupports({
|
||||
accountID: account.id, page_size: supportsCount, claimID: givenClaim });
|
||||
const supports = (await supportsResponse.json()).result.items;
|
||||
const paginator = new GenericPager(this.client, message, {
|
||||
items: supports,
|
||||
header: `All supports for the trusted account${
|
||||
givenClaim ? ` on claim \`${givenClaim}\`` : ''}`, itemTitle: 'Supports', itemsPerPage: 5,
|
||||
display: item => `> ${item.name} \`${item.claim_id}\`\n> ${item.amount} LBC\n`
|
||||
});
|
||||
return paginator.start(message.channel.id, message.author.id);
|
||||
}
|
||||
get metadata() { return {
|
||||
category: 'Trusted',
|
||||
description: 'Shows the list of supports from the trusted account.',
|
||||
usage: '[claimID]'
|
||||
}; }
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
const { default: Redis } = require('ioredis');
|
||||
const redis = require('redis');
|
||||
const { EventEmitter } = require('eventemitter3');
|
||||
|
||||
/**
|
||||
|
@ -19,7 +19,7 @@ module.exports = class Database extends EventEmitter {
|
|||
connect({ host = 'localhost', port, password, prefix }) {
|
||||
console.info('Connecting to redis...');
|
||||
return new Promise((resolve, reject) => {
|
||||
this.redis = new Redis(port, host, { password, keyPrefix: prefix });
|
||||
this.redis = redis.createClient({ host, port, password, prefix });
|
||||
this.redis.on('error', this.onError.bind(this));
|
||||
this.redis.on('warning', w => console.warn('Redis Warning', w));
|
||||
this.redis.on('end', () => this.onClose.bind(this));
|
||||
|
@ -37,32 +37,67 @@ module.exports = class Database extends EventEmitter {
|
|||
|
||||
// #region Redis functions
|
||||
hget(key, hashkey) {
|
||||
return this.redis.hget(key, hashkey);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.redis.HGET(key, hashkey, (err, value) => {
|
||||
if (err) reject(err);
|
||||
resolve(value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
hset(key, hashkey, value) {
|
||||
return this.redis.hset(key, hashkey, value);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.redis.HSET(key, hashkey, value, (err, res) => {
|
||||
if (err) reject(err);
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
incr(key) {
|
||||
return this.redis.incr(key);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.redis.incr(key, (err, res) => {
|
||||
if (err) reject(err);
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get(key) {
|
||||
return this.redis.get(key);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.redis.get(key, function(err, reply) {
|
||||
if (err) reject(err);
|
||||
resolve(reply);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
expire(key, ttl) {
|
||||
return this.redis.expire(key, ttl);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.redis.expire(key, ttl, (err, value) => {
|
||||
if (err) reject(err);
|
||||
resolve(value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
exists(key) {
|
||||
return this.redis.exists(key);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.redis.exists(key, (err, value) => {
|
||||
if (err) reject(err);
|
||||
resolve(value === 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
return this.redis.set(key, value);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.redis.set(key, value, (err, res) => {
|
||||
if (err) reject(err);
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
// #endregion
|
||||
|
||||
|
|
|
@ -40,11 +40,11 @@ module.exports = class Events {
|
|||
}
|
||||
}
|
||||
|
||||
onReaction(message, emoji, member) {
|
||||
const id = `${message.id}:${member.id}`;
|
||||
onReaction(message, emoji, userID) {
|
||||
const id = `${message.id}:${userID}`;
|
||||
if (this.client.messageAwaiter.reactionCollectors.has(id)) {
|
||||
const collector = this.client.messageAwaiter.reactionCollectors.get(id);
|
||||
collector._onReaction(emoji, member.id);
|
||||
collector._onReaction(emoji, userID);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -42,9 +42,6 @@ class Command {
|
|||
` \`${this.metadata.usage}\`` : ''}`);
|
||||
|
||||
// Check commmand permissions
|
||||
const curators = Array.isArray(config.curatorRoleID) ? config.curatorRoleID : [config.curatorRoleID];
|
||||
const admins = Array.isArray(config.adminRoleID) ? config.adminRoleID : [config.adminRoleID];
|
||||
const trusteds = Array.isArray(config.trustedRoleID) ? config.trustedRoleID : [config.trustedRoleID];
|
||||
if (this.options.permissions.length)
|
||||
for (const i in this.options.permissions) {
|
||||
const perm = this.options.permissions[i];
|
||||
|
@ -56,22 +53,13 @@ class Command {
|
|||
embed: 'I need the permission `Embed Links` to use this command!',
|
||||
emoji: 'I need the permission `Use External Emojis` to use this command!',
|
||||
elevated: 'Only the elevated users of the bot can use this command!',
|
||||
curator: `This command requires you to have the ${
|
||||
curators.map(id =>
|
||||
`"${this.client.guilds.get(config.guildID).roles.get(id).name}"`).join('/')} role!`,
|
||||
admin: `This command requires you to have the ${
|
||||
admins.map(id =>
|
||||
`"${this.client.guilds.get(config.guildID).roles.get(id).name}"`).join('/')} role!`,
|
||||
curatorOrAdmin: `This command requires you to have the ${
|
||||
curators.map(id =>
|
||||
`"${this.client.guilds.get(config.guildID).roles.get(id).name}"`).join('/')} or ${
|
||||
admins.map(id =>
|
||||
`"${this.client.guilds.get(config.guildID).roles.get(id).name}"`).join('/')} role!`,
|
||||
trustedOrAdmin: `This command requires you to have the ${
|
||||
trusteds.map(id =>
|
||||
`"${this.client.guilds.get(config.guildID).roles.get(id).name}"`).join('/')} or ${
|
||||
admins.map(id =>
|
||||
`"${this.client.guilds.get(config.guildID).roles.get(id).name}"`).join('/')} role!`,
|
||||
curator: `This command requires you to have the "${
|
||||
message.guild.roles.get(config.curatorRoleID).name}" role!`,
|
||||
admin: `This command requires you to have the "${
|
||||
message.guild.roles.get(config.adminRoleID).name}" role!`,
|
||||
curatorOrAdmin: `This command requires you to have the "${
|
||||
message.guild.roles.get(config.curatorRoleID).name}" or "${
|
||||
message.guild.roles.get(config.adminRoleID).name}" roles!`,
|
||||
guild: 'This command must be ran in a guild!',
|
||||
}[perm]);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class GenericPager extends Paginator {
|
|||
constructor(client, message, {
|
||||
items = [], itemsPerPage = 15,
|
||||
display = item => item.toString(),
|
||||
embedExtra = {}, itemTitle = 'Items',
|
||||
embedExtra = {}, itemTitle = 'words.item.many',
|
||||
header = null, footer = null
|
||||
} = {}) {
|
||||
super(client, message, { items, itemsPerPage });
|
||||
|
@ -70,7 +70,7 @@ class GenericPager extends Paginator {
|
|||
value: displayPage.join('\n')
|
||||
});
|
||||
|
||||
return { embeds: [embed] };
|
||||
return { embed };
|
||||
} else {
|
||||
const top = `${this.itemTitle} ` +
|
||||
`(${this.items.length}, Page ${this.pageNumber}/${this.maxPages})`;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const fetch = require('node-fetch');
|
||||
const AbortController = require('abort-controller');
|
||||
const config = require('config');
|
||||
const Util = require('../util');
|
||||
|
||||
|
@ -180,13 +182,10 @@ class LBRY {
|
|||
}
|
||||
|
||||
/**
|
||||
* List account addresses or details.
|
||||
* @param {object} options
|
||||
* @param {string} options.to How many items should be per page
|
||||
* @param {string} options.amount The amount to send
|
||||
* List account addresses or details of single address.
|
||||
*/
|
||||
listAddresses({ page_size = 1, account_id } = {}) {
|
||||
return this._sdkRequest('address_list', { page_size, account_id });
|
||||
listAddresses() {
|
||||
return this._sdkRequest('address_list', { page_size: 1 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
106
src/util.js
106
src/util.js
|
@ -1,6 +1,5 @@
|
|||
const fetch = require('node-fetch');
|
||||
const config = require('config');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* Represents the utilities for the bot
|
||||
|
@ -49,7 +48,7 @@ Util.Prefix = {
|
|||
Util.Prefix.regex(client, prefixes), '$2').replace(/\s\s+/g, ' ').trim();
|
||||
},
|
||||
escapeRegex(s) {
|
||||
return s.replace(/[-/\\^$*+?.()|[\]{}!]/g, '\\$&');
|
||||
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -69,40 +68,24 @@ Util.CommandPermissions = {
|
|||
curator: (client, message) => {
|
||||
const member = message.guildID ? message.member :
|
||||
client.guilds.get(config.guildID).members.get(message.author.id);
|
||||
const roles = Array.isArray(config.curatorRoleID) ? config.curatorRoleID : [config.curatorRoleID];
|
||||
if (!member) return false;
|
||||
if (Util.CommandPermissions.elevated(client, message)) return true;
|
||||
return roles.map(r => member.roles.includes(r)).includes(true);
|
||||
return member.roles.includes(config.curatorRoleID);
|
||||
},
|
||||
admin: (client, message) => {
|
||||
const member = message.guildID ? message.member :
|
||||
client.guilds.get(config.guildID).members.get(message.author.id);
|
||||
const roles = Array.isArray(config.adminRoleID) ? config.adminRoleID : [config.adminRoleID];
|
||||
if (!member) return false;
|
||||
if (Util.CommandPermissions.elevated(client, message)) return true;
|
||||
return roles.map(r => member.roles.includes(r)).includes(true);
|
||||
return member.roles.includes(config.adminRoleID);
|
||||
},
|
||||
curatorOrAdmin: (client, message) => {
|
||||
const member = message.guildID ? message.member :
|
||||
client.guilds.get(config.guildID).members.get(message.author.id);
|
||||
const roles = [
|
||||
...(Array.isArray(config.adminRoleID) ? config.adminRoleID : [config.adminRoleID]),
|
||||
...(Array.isArray(config.curatorRoleID) ? config.curatorRoleID : [config.curatorRoleID]),
|
||||
];
|
||||
if (!member) return false;
|
||||
if (Util.CommandPermissions.elevated(client, message)) return true;
|
||||
return roles.map(r => member.roles.includes(r)).includes(true);
|
||||
},
|
||||
trustedOrAdmin: (client, message) => {
|
||||
const member = message.guildID ? message.member :
|
||||
client.guilds.get(config.guildID).members.get(message.author.id);
|
||||
const roles = [
|
||||
...(Array.isArray(config.adminRoleID) ? config.adminRoleID : [config.adminRoleID]),
|
||||
...(Array.isArray(config.trustedRoleID) ? config.trustedRoleID : [config.trustedRoleID]),
|
||||
];
|
||||
if (!member) return false;
|
||||
if (Util.CommandPermissions.elevated(client, message)) return true;
|
||||
return roles.map(r => member.roles.includes(r)).includes(true);
|
||||
return member.roles.includes(config.curatorRoleID) ||
|
||||
member.roles.includes(config.adminRoleID);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -162,20 +145,6 @@ Util.resolveToUserID = (arg) => {
|
|||
else return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve argument to a claim ID
|
||||
* @memberof Util.
|
||||
* @param {string} arg
|
||||
* @returns {?string}
|
||||
*/
|
||||
Util.resolveToClaimID = (arg) => {
|
||||
if (/^[a-f0-9]{40}$/.test(arg))
|
||||
return arg;
|
||||
else if (/^lbry:\/\/@?[\w-]+#([a-f0-9]{40})$/.test(arg))
|
||||
return arg.replace(/^lbry:\/\/@?[\w-]+#([a-f0-9]{40})$/, '$1');
|
||||
else return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a promise that resolves after some time
|
||||
* @memberof Util.
|
||||
|
@ -232,26 +201,6 @@ Util.Hastebin = {
|
|||
* @memberof Util.
|
||||
*/
|
||||
Util.LBRY = {
|
||||
async syncPairs(client) {
|
||||
const response = await client.lbry.listAccounts({ page_size: await Util.LBRY.getAccountCount(client) });
|
||||
const accounts = await response.json();
|
||||
|
||||
let syncedAccounts = 0;
|
||||
for (const account of accounts.result.items) {
|
||||
if (/\d{17,19}/.test(account.name)) {
|
||||
if (await client.sqlite.get(account.name)) continue;
|
||||
await client.sqlite.pair(account.name, account.id);
|
||||
syncedAccounts++;
|
||||
}
|
||||
}
|
||||
|
||||
return syncedAccounts;
|
||||
},
|
||||
async findSDKAccount(client, fn) {
|
||||
const response = await client.lbry.listAccounts({ page_size: await Util.LBRY.getAccountCount(client) });
|
||||
const accounts = await response.json();
|
||||
return accounts.result.items.find(fn);
|
||||
},
|
||||
async findOrCreateAccount(client, discordID, create = true) {
|
||||
// Check SQLite
|
||||
const pair = await client.sqlite.get(discordID);
|
||||
|
@ -259,7 +208,9 @@ Util.LBRY = {
|
|||
return { accountID: pair.lbryID };
|
||||
|
||||
// Check accounts via SDK
|
||||
const foundAccount = await Util.LBRY.findSDKAccount(client, account => account.name === discordID);
|
||||
const response = await client.lbry.listAccounts({ page_size: await Util.LBRY.getAccountCount(client) });
|
||||
const accounts = await response.json();
|
||||
const foundAccount = accounts.result.items.find(account => account.name === discordID);
|
||||
if (foundAccount) {
|
||||
await client.sqlite.pair(discordID, foundAccount.id);
|
||||
return { accountID: foundAccount.id };
|
||||
|
@ -299,27 +250,14 @@ Util.LBRY = {
|
|||
return Number.isInteger(num) ? `${num}.0` : num.toString();
|
||||
},
|
||||
async deleteAccount(client, discordID, lbryID) {
|
||||
// Backup the wallet before doing any delete function
|
||||
try {
|
||||
Util.LBRY.backupWallet();
|
||||
} catch (err) {
|
||||
console.error('Error occurred while backing up wallet file!');
|
||||
console.error(err);
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Abandon supports
|
||||
await Util.LBRY.abandonAllClaims(client, lbryID);
|
||||
|
||||
// Take out funds from account
|
||||
const balanceResponse = await client.lbry.accountBalance(lbryID);
|
||||
let amount = (await balanceResponse.json()).result.total;
|
||||
while (amount >= 2) {
|
||||
const amount = (await balanceResponse.json()).result.total;
|
||||
if (parseFloat(amount) > 0)
|
||||
await client.lbry.fundAccount({ from: lbryID, everything: true, amount });
|
||||
const finalBalance = await client.lbry.accountBalance(lbryID);
|
||||
amount = (await finalBalance.json()).result.total;
|
||||
await Util.halt(3000);
|
||||
}
|
||||
|
||||
// Remove account from SDK & SQLite
|
||||
await client.lbry.removeAccount(lbryID);
|
||||
|
@ -336,27 +274,7 @@ Util.LBRY = {
|
|||
for (let i = 0, len = supports.length; i < len; i++) {
|
||||
const support = supports[i];
|
||||
await client.lbry.abandonSupport({ claimID: support.claim_id, accountID: lbryID });
|
||||
await Util.halt(3000);
|
||||
}
|
||||
return { count: supports.length };
|
||||
},
|
||||
backupWallet() {
|
||||
const wallet = fs.readFileSync(config.walletPath);
|
||||
const d = new Date();
|
||||
const date = [
|
||||
d.getUTCFullYear(),
|
||||
d.getUTCMonth().toString().padStart(2, '0'),
|
||||
d.getUTCDay().toString().padStart(2, '0'),
|
||||
].join('-');
|
||||
const time = [
|
||||
d.getUTCHours().toString().padStart(2, '0'),
|
||||
d.getUTCMinutes().toString().padStart(2, '0'),
|
||||
d.getUTCSeconds().toString().padStart(2, '0'),
|
||||
d.getUTCMilliseconds().toString()
|
||||
].join('-');
|
||||
const backupName = 'default_wallet.' + date + '_' + time + '.bak';
|
||||
const backupPath = path.join(config.walletBackupFolder, backupName);
|
||||
fs.writeFileSync(backupPath, wallet);
|
||||
console.log(`Backed up wallet file: ${backupPath}`);
|
||||
}
|
||||
};
|
||||
};
|
Loading…
Add table
Reference in a new issue