├── .gitignore ├── README.md ├── gulpfile.js ├── package.json ├── src ├── index.ts └── lib │ └── Storage.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | data-store.json 2 | config.json 3 | /node_modules/* 4 | /bin/* 5 | guild-storage.json 6 | bot-storage.json 7 | npm-debug* 8 | bottest.js 9 | /pkg/* 10 | /storage/* 11 | /typings/* 12 | /.vscode/* 13 | yarn* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # discord-storage 2 | 3 | discord-storage is a revolutionary way to horribly store your data! Written using [discord.js](http://github.com/hydrabolt/discord.js), discord-storage allows data to be stored within a Discord server text channel. This project was written as a joke partially inspired by a conversation with @bdistin about storing data on discord, and by [this project](https://github.com/rossem/RedditStorage). 4 | 5 | ## Advantages: 6 | - None! 7 | 8 | ## Disadvantages: 9 | - Slow (very!) 10 | - Reliant on the Discord API (ratelimits!) 11 | - Requires setting up your own Discord bot 12 | - Stupid! 13 | 14 | # Getting started 15 | It's pretty simple to use: 16 | ```js 17 | const Discord = require('discord.js'); 18 | const Storage = require('discord-storage').Storage; 19 | 20 | const client = new Discord.Client(); 21 | client.login('discord bot token'); 22 | 23 | client.once('ready', () => { 24 | client.storage = new Storage(client, 'storageChannelIDGoesHere'); 25 | client.storage.sync().then(() => { 26 | // Do whatever you want with storage after syncing is complete 27 | }); 28 | }); 29 | ``` 30 | 31 | I honestly don't want to bother with documenting the methods so just check the source. Not like you're going to use this anyway! -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var ts = require('gulp-typescript'); 3 | var del = require('del'); 4 | 5 | gulp.task('default', () => 6 | { 7 | del.sync(['./bin/**/*.*']); 8 | gulp.src('./src/**/*.ts') 9 | .pipe(ts({ 10 | noImplicitAny: true, 11 | outDir: 'bin', 12 | target: 'ES6', 13 | module: 'commonjs', 14 | moduleResolution: 'node' 15 | })) 16 | .pipe(gulp.dest('bin/')); 17 | gulp.src('./src/config.json') 18 | .pipe(gulp.dest('bin/')); 19 | }); 20 | 21 | gulp.task('package', (done) => 22 | { 23 | gulp.src('src/**/*ts') 24 | .pipe(ts({ 25 | noImplicitAny: true, 26 | outDir: 'bin', 27 | target: 'ES6', 28 | module: 'commonjs', 29 | moduleResolution: 'node' 30 | })) 31 | .pipe(gulp.dest('pkg/discord-storage/bin')); 32 | gulp.src('src/**/*.json') 33 | .pipe(gulp.dest('pkg/discord-storage/bin')); 34 | gulp.src(['package.json', '*.md']) 35 | .pipe(gulp.dest('pkg/discord-storage')); 36 | done(); 37 | }); 38 | 39 | gulp.task('clean-package', (done) => 40 | { 41 | del.sync(['pkg/discord-storage/bin/**', '!pkg/discord-storage/bin']); 42 | done(); 43 | }); 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discord-storage", 3 | "version": "0.1.1", 4 | "description": "Stores data in a specified discord channel that your client has access to", 5 | "main": "bin/index.js", 6 | "scripts": { 7 | "package": "gulp clean-package && gulp package" 8 | }, 9 | "author": "Zack Campbell ", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@types/node": "^6.0.58", 13 | "del": "^2.2.2", 14 | "gulp": "^3.9.1", 15 | "gulp-typescript": "^3.1.4", 16 | "tslint": "^4.3.1", 17 | "typescript": "^2.1.4" 18 | }, 19 | "dependencies": { 20 | "discord.js": "^11.0.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import _Storage from './lib/Storage'; 2 | 3 | export const Storage: any = _Storage; 4 | export default Storage; 5 | -------------------------------------------------------------------------------- /src/lib/Storage.ts: -------------------------------------------------------------------------------- 1 | import { Client, TextChannel, Message, Collection } from 'discord.js'; 2 | 3 | export default class Storage 4 | { 5 | private _client: Client; 6 | private _channel: TextChannel; 7 | private _cache: Collection; 8 | 9 | public constructor(client: Client, channel: TextChannel | string) 10 | { 11 | this._client = client; 12 | const id: string = ( channel).id ? ( channel).id : channel; 13 | this._channel = this._client.channels.get(id); 14 | this._cache = new Collection(); 15 | } 16 | 17 | /** 18 | * Find the message containing the stored item 19 | */ 20 | private _find(key: string): Message 21 | { 22 | const message: Message = this._cache.find((m: Message) => 23 | m.content.includes(`"key":"${key}"`)); 24 | return message || null; 25 | } 26 | 27 | /** 28 | * Index the storage channel, caching all messages 29 | */ 30 | public async sync(): Promise 31 | { 32 | let messages: any = await this._channel.fetchMessages({ limit: 100 }); 33 | while (true) 34 | { 35 | if (messages.size < 100) break; 36 | let fetched: any = await this._channel.fetchMessages({ limit: 100, before: messages.last().id }); 37 | messages = messages.concat(fetched); 38 | if (fetched.size < 100) break; 39 | } 40 | this._cache = messages; 41 | } 42 | 43 | /** 44 | * Check if stored key exists 45 | */ 46 | public exists(key: string): boolean 47 | { 48 | return Boolean(this._find(key)); 49 | } 50 | 51 | /** 52 | * Set a value in storage 53 | */ 54 | public async set(key: string, value: any): Promise 55 | { 56 | if (JSON.stringify({key: key, value: value}).length > 1990) 57 | throw new RangeError('Data is too large to be stored'); 58 | const message: Message = this._find(key); 59 | const data: string = JSON.stringify({ key: key, value: value}); 60 | if (message) 61 | { 62 | message.content = data; 63 | this._cache.set(message.id, message); 64 | message.edit(data); 65 | } 66 | else 67 | { 68 | const msg: Message = await this._channel.send(data); 69 | this._cache.set(msg.id, msg); 70 | } 71 | } 72 | 73 | /** 74 | * Get a value from storage 75 | */ 76 | public get(key: string): any 77 | { 78 | const message: Message = this._find(key); 79 | if (message) return JSON.parse(message.content).value; 80 | return null; 81 | } 82 | 83 | /** 84 | * Remove a value from storage 85 | */ 86 | public async remove(key: string): Promise 87 | { 88 | const message: Message = this._find(key); 89 | if (!message) return; 90 | await message.delete(); 91 | this._cache.delete(message.id); 92 | } 93 | 94 | /** 95 | * Clear all data from the channel 96 | */ 97 | public async clear(): Promise 98 | { 99 | while (true) 100 | { 101 | const msgs: any = await this._channel.fetchMessages({ limit: 100 }); 102 | if (msgs.size === 0) break; 103 | if (msgs.size === 1) await msgs.deleteAll(); 104 | else await this._channel.bulkDelete(msgs); 105 | if (msgs.size < 100) break; 106 | } 107 | this._cache.clear(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "lib": [ 6 | "es7" 7 | ] 8 | }, 9 | "exclude": [ 10 | "node_modules", 11 | "bower_components", 12 | "jspm_packages", 13 | "tmp", 14 | "temp", 15 | "bin", 16 | "docs", 17 | "pkg", 18 | "examples" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-inferrable-types": false, 4 | "no-unused-expression": true, 5 | "no-duplicate-variable": true, 6 | "no-duplicate-key": true, 7 | "no-unused-variable": [true, {"ignore-pattern": "^_"}], 8 | "no-invalid-this": true, 9 | "no-shadowed-variable": true, 10 | "comment-format": [ 11 | true, "check-space" 12 | ], 13 | "indent": [ 14 | true, "tabs" 15 | ], 16 | "curly": false, 17 | "class-name": true, 18 | "semicolon": [true], 19 | "triple-equals": true, 20 | "eofline": true, 21 | "no-bitwise": false, 22 | "no-console": [false], 23 | // "member-ordering": [ 24 | // true, { "order": [ 25 | // "protected-static-field", 26 | // "private-static-field", 27 | // "public-static-field", 28 | // "protected-instance-field", 29 | // "private-instance-field", 30 | // "public-instance-field", 31 | // "constructor", 32 | // "protected-instance-method", 33 | // "private-instance-method", 34 | // "public-instance-method", 35 | // "private-static-method", 36 | // "protected-static-method", 37 | // "public-static-method" 38 | // ]} 39 | // ], 40 | "member-access": [true, "check-accessor", "check-constructor"], 41 | "no-consecutive-blank-lines": true, 42 | "no-constructor-vars": true, 43 | "one-line": [ 44 | false 45 | ], 46 | "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"], 47 | "interface-name": [true, "always-prefix"], 48 | "no-conditional-assignment": true, 49 | "use-isnan": true, 50 | "no-trailing-whitespace": true, 51 | "quotemark": [true, "single", "avoid-escape"], 52 | "no-unreachable": true, 53 | "no-use-before-declare": true, 54 | "whitespace": [true, 55 | "check-branch", 56 | "check-decl", 57 | "check-operator", 58 | "check-module", 59 | "check-separator", 60 | "check-type", 61 | "check-typecast" 62 | ], 63 | "typedef": [ 64 | "parameter", 65 | "arrow-parameter", 66 | "call-signature", 67 | "member-variable-declaration", 68 | "property-declaration", 69 | "variable-declaration" 70 | ], 71 | "typedef-whitespace": [ 72 | true, 73 | { 74 | "call-signature": "nospace", 75 | "index-signature": "nospace", 76 | "parameter": "nospace", 77 | "property-declaration": "nospace", 78 | "variable-declaration": "nospace" 79 | }, 80 | { 81 | "call-signature": "onespace", 82 | "index-signature": "onespace", 83 | "parameter": "onespace", 84 | "property-declaration": "onespace", 85 | "variable-declaration": "onespace" 86 | } 87 | ] 88 | } 89 | } --------------------------------------------------------------------------------