├── db ├── newQuotes.csv ├── quotes.count.yml ├── quotes.db ├── wikis.js ├── countQuotes.js ├── jsonToDb.py ├── csvToDB.py ├── icons.js ├── addQuote.js ├── portraits.js ├── quotes.db.csv └── quotes.db.sql ├── CNAME ├── Procfile ├── riot.txt ├── img ├── Logo.png ├── Tilde.png ├── Demo Picture.png ├── Stock Demo.png ├── Weather Demo.png └── Logo.svg ├── _config.yml ├── .replit ├── .github ├── FUNDING.yml ├── workflows │ ├── wiki_upd.sh │ ├── wiki-copy.yml │ ├── sqlite-dump.yml │ ├── csv-convert.yml │ ├── ci.yml │ └── codeql-analysis.yml └── dependabot.yml ├── wiki ├── Home.md ├── Help.md └── Hosting.md ├── .eslintrc.yml ├── data └── opggRegions.json ├── config-example.json ├── .deepsource.toml ├── Dockerfile ├── extras └── changeBotAvatar.js ├── .env.example ├── LICENSE ├── package.json ├── .gitignore ├── README.md └── index.js /db/newQuotes.csv: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | quotobot.js.org -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: node . -------------------------------------------------------------------------------- /db/quotes.count.yml: -------------------------------------------------------------------------------- 1 | count: 210 2 | -------------------------------------------------------------------------------- /riot.txt: -------------------------------------------------------------------------------- 1 | 6f1f5b0b-d3c7-445a-9988-b56adcb60132 2 | -------------------------------------------------------------------------------- /db/quotes.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-Gigabyte/quotobot/HEAD/db/quotes.db -------------------------------------------------------------------------------- /img/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-Gigabyte/quotobot/HEAD/img/Logo.png -------------------------------------------------------------------------------- /img/Tilde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-Gigabyte/quotobot/HEAD/img/Tilde.png -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect 2 | title: Quotobot 3 | show_downloads: false 4 | -------------------------------------------------------------------------------- /img/Demo Picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-Gigabyte/quotobot/HEAD/img/Demo Picture.png -------------------------------------------------------------------------------- /img/Stock Demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-Gigabyte/quotobot/HEAD/img/Stock Demo.png -------------------------------------------------------------------------------- /img/Weather Demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-Gigabyte/quotobot/HEAD/img/Weather Demo.png -------------------------------------------------------------------------------- /.replit: -------------------------------------------------------------------------------- 1 | run="npm start" 2 | language="nodejs" 3 | onBoot="echo Booting up! Make sure to set your environment variables." 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | custom: ['https://github.com/Team-Gigabyte/donate'] 4 | -------------------------------------------------------------------------------- /wiki/Home.md: -------------------------------------------------------------------------------- 1 | Welcome to the quotobot wiki! 2 | * *Help:* lists all the commands and how to use them. 3 | * *Hosting:* gives the steps for hosting your own Quotobot instance. -------------------------------------------------------------------------------- /db/wikis.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "*The Scarlet Pimpernel* by Baroness Orczy": "The Scarlet Pimpernel", 3 | "QB Devs": null, 4 | "Anonymous": "Anonymous work" 5 | } -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | node: true 3 | commonjs: true 4 | es2020: true 5 | extends: 'eslint:recommended' 6 | parserOptions: 7 | ecmaVersion: 11 8 | rules: 9 | no-unused-vars: warn -------------------------------------------------------------------------------- /.github/workflows/wiki_upd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CURRWD=$(pwd) 3 | mkdir -p ./wiki 4 | mkdir -p ~/wikitemp 5 | cd ~/wikitemp 6 | git clone https://github.com/Team-Gigabyte/quotobot.wiki . 7 | for i in *.md; do cp $i $CURRWD/wiki/$i; done -------------------------------------------------------------------------------- /data/opggRegions.json: -------------------------------------------------------------------------------- 1 | { 2 | "kr": "www", 3 | "na1": "na", 4 | "jp1": "jp", 5 | "ru": "ru", 6 | "euw1": "euw", 7 | "br1": "br", 8 | "oc1": "oce", 9 | "eun1": "eune", 10 | "tr1": "tr", 11 | "la1": "lan", 12 | "la2": "las" 13 | } -------------------------------------------------------------------------------- /db/countQuotes.js: -------------------------------------------------------------------------------- 1 | const sqlite3 = require("sqlite3"); 2 | const db = new sqlite3.Database('./db/quotes.db'); 3 | db.get("Select Count(*) from Quotes", (err, row) => { 4 | if (err) { console.error(err.message); } 5 | return row ? console.table(row) : console.log("Nothing found."); 6 | }) -------------------------------------------------------------------------------- /config-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "~", 3 | "token": "your-token-here-inside-these-quotes", 4 | "instructions": "See the README.md file for info", 5 | "help-domain-example": "example.com", 6 | "clientID-example": "type-in-your-clientID-here", 7 | "permissionValue": 0, 8 | "weather-token": "OpenWeatherMap-token-here" 9 | } -------------------------------------------------------------------------------- /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "python" 5 | enabled = true 6 | 7 | [analyzers.meta] 8 | runtime_version = "3.x.x" 9 | 10 | [[analyzers]] 11 | name = "javascript" 12 | enabled = true 13 | 14 | [analyzers.meta] 15 | environment = ["nodejs"] 16 | 17 | [[analyzers]] 18 | name = "shell" 19 | enabled = true -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine 2 | 3 | # Create Directory for Workdir 4 | RUN mkdir -p /app 5 | 6 | # Directory Workdir location apps 7 | WORKDIR /app 8 | 9 | # Copy file app to container 10 | ADD ./* /app/ 11 | 12 | # Rename config & install module 13 | RUN cp /app/config-example.json /app/config.json 14 | 15 | RUN npm install 16 | 17 | CMD [ "node", "/app/index.js" ] 18 | -------------------------------------------------------------------------------- /extras/changeBotAvatar.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js") 2 | const bot = new Discord.Client(); 3 | const readline = require('readline').createInterface({ 4 | input: process.stdin, 5 | output: process.stdout 6 | }) 7 | readline.question("What's the bot token? ", ans => { 8 | bot.login(ans) 9 | readline.question("What's the URL/path of the avatar? ", url => { 10 | bot.user.setAvatar(url).then(() => { 11 | console.log("All done!") 12 | process.exit(0) 13 | }).catch(e => { throw e }) 14 | }) 15 | }) -------------------------------------------------------------------------------- /db/jsonToDb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sqlite3 3 | import json 4 | data = json.load(open("quotes.json")) 5 | db = sqlite3.connect("quotes2.db") 6 | count = 67 7 | source = "Scarlet Pimpernel by Baroness Orczy" 8 | for q in data[source]: 9 | count += 1 10 | #db.cursor().execute("insert into Quotes(quote, id, source, usage) values('" +q+"}', "+str(count)+", 'George Washington', 0)") 11 | db.cursor().execute("insert into Quotes(quote, id, source, usage) values(?,?,?,?)",(q, count, source, 0)) 12 | #print(data["Thomas Jefferson"]) 13 | db.commit() 14 | db.close() -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "daily" 16 | -------------------------------------------------------------------------------- /db/csvToDB.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import sqlite3 3 | db = sqlite3.connect("quotes.db") 4 | getID = db.cursor().execute("SELECT id FROM Quotes ORDER BY id DESC LIMIT 1;") 5 | lastID = 0 6 | for row in getID: 7 | lastID = row[0] 8 | with open('./newQuotes.csv') as csv_file: 9 | csv_reader = csv.reader(csv_file, delimiter=',') 10 | line_count = 0 11 | for row in csv_reader: 12 | print(row) 13 | db.cursor().execute( 14 | "insert into Quotes(quote, id, source, usage) values(?,?,?,?);", 15 | (row[0], lastID + 1, row[1], 0)) 16 | line_count += 1 17 | lastID += 1 18 | print(f'Added {line_count} quotes.') 19 | db.commit() 20 | db.close() 21 | -------------------------------------------------------------------------------- /db/icons.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | quote: "https://cdn.discordapp.com/attachments/449680513683292162/771800588446335026/qblogo.png", // from https://materialdesignicons.com/icon/comment-quote licensed under SIL OFL 3 | empty: "https://cdn.discordapp.com/attachments/449680513683292162/746829996752109678/Untitled.png", 4 | info: "https://cdn.discordapp.com/attachments/449680513683292162/748682998022537287/information_2139.png", // this and below from Twemoji licensed under CC-BY 4.0 5 | warn: "https://cdn.discordapp.com/attachments/449680513683292162/751892501375221862/warning_26a0.png", 6 | bulb: "https://cdn.discordapp.com/attachments/449680513683292162/797539574217179196/light-bulb_1f4a1.png", 7 | } -------------------------------------------------------------------------------- /db/addQuote.js: -------------------------------------------------------------------------------- 1 | const sqlite3 = require("sqlite3"); 2 | const db = new sqlite3.Database('./db/quotes.db'); 3 | const readline = require("readline"); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | output: process.stdout 7 | }); 8 | rl.question("What is the quote? ", function (qt) { 9 | rl.question("Who wrote it? ", function (src) { 10 | db.each("SELECT * FROM Quotes ORDER BY id DESC limit 1;", function (error, row) { 11 | if (error) { console.error(error) } 12 | db.run(`INSERT INTO Quotes(quote, id, source, usage) VALUES(?,?,?,?)`, 13 | [qt, row.id + 1, src, 0], function (error) { 14 | if (error) { console.error(error) } 15 | else { console.log("Added quote!") } 16 | } 17 | );//SELECT * FROM Quotes ORDER BY id ASC limit 1; 18 | rl.close(); 19 | }); 20 | }); 21 | }); -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # if you're using dotenv 2 | # copy this file and rename to .env and 3 | # add a # to the beginning of any line you don't have the value or key for 4 | QBTOKEN= 5 | QBSTATUS= 6 | # ^ optional, default quotobot.js.org (will be prefixed with "Watching"), also inserted when the user clicks "Share to Twitter" 7 | QBHELPURL= 8 | # ^ optional, default link is https://quotobot.js.org/wiki/Help 9 | QBPREFIX= 10 | # ^ optional, default ~ 11 | QBWEATHER= 12 | # ^ OpenWeatherMap key 13 | QBWTIMEOUT= 14 | # ^ optional, default 15000 (15 seconds) 15 | QBSTOCKS= 16 | # ^ Finnhub key 17 | QBSTIMEOUT= 18 | # ^ optional, default 2000 (2 seconds) or QBWTIMEOUT if that is set 19 | QBRGKEY= 20 | # ^ Riot API key (enclosing the key in quotes may be required) 21 | QBLEAGUETIMEOUT= 22 | # ^ optional, default 5000 (5 seconds) 23 | QBBAN= 24 | # ^ optional, the bot won't respond to this user id's commands (id's are a long string of numbers which you can get from the Discord app) 25 | -------------------------------------------------------------------------------- /.github/workflows/wiki-copy.yml: -------------------------------------------------------------------------------- 1 | name: Update wiki copy 2 | 3 | on: 4 | schedule: 5 | - cron: 30 1 * * * 6 | workflow_dispatch: 7 | 8 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 9 | jobs: 10 | update: 11 | # The type of runner that the job will run on 12 | runs-on: ubuntu-latest 13 | 14 | # Steps represent a sequence of tasks that will be executed as part of the job 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Update submodules 18 | run: chmod +x .github/workflows/wiki_upd.sh && bash .github/workflows/wiki_upd.sh 19 | - name: Commit the new wiki copy 20 | uses: stefanzweifel/git-auto-commit-action@1f4914882d31162256a5dd23dd006bf97be303a2 21 | with: 22 | commit_message: Update the wiki copy 23 | file_pattern: 'wiki/*' 24 | - name: Notify if the workflow is broken 25 | uses: sarisia/actions-status-discord@v1 26 | if: failure() 27 | with: 28 | webhook: ${{ secrets.DISCORD_WEBHOOK }} 29 | -------------------------------------------------------------------------------- /.github/workflows/sqlite-dump.yml: -------------------------------------------------------------------------------- 1 | name: SQLite Dump 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | 7 | jobs: 8 | sqlitedump: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - name: Dump the SQLite to a SQL File 13 | run: for i in ./db/*.db; do sqlite3 $i .dump > $i.sql; done 14 | - name: Dump the SQLite to CSV 15 | run: for i in ./db/*.db; do sqlite3 -header -csv $i "select * from Quotes order by id Asc;" > $i.csv; done 16 | - name: Count the quotes and write it to a YAML file 17 | run: | 18 | cd ./db; COUNT=$(sqlite3 quotes.db "Select Count(*) from Quotes"); echo "count: $COUNT" > quotes.count.yml 19 | - name: Commit the SQLite dumps 20 | uses: stefanzweifel/git-auto-commit-action@1f4914882d31162256a5dd23dd006bf97be303a2 21 | with: 22 | commit_message: SQLite database dump 23 | file_pattern: db/*.db.* db/*.yml 24 | - name: Notify if the code is broken 25 | uses: sarisia/actions-status-discord@v1 26 | if: failure() 27 | with: 28 | webhook: ${{ secrets.DISCORD_WEBHOOK }} 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Team Gigabyte 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quotobot", 3 | "version": "2.5.1", 4 | "description": "A Discord bot that tells quotes", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "dev": "nodemon --watch .env --watch . --watch ./db --watch ./data -e js,json,db", 9 | "count": "node ./db/countQuotes.js", 10 | "add": "node ./db/addQuote.js", 11 | "lint": "eslint .", 12 | "relock": "npm i --package-lock-only", 13 | "changeAvatar": "node extras/changeBotAvatar.js", 14 | "updateqb": "git checkout master && git pull origin && rm -rf ./node_modules && npm i" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/Team-Gigabyte/quotobot" 19 | }, 20 | "author": "Team Gigabyte", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/Team-Gigabyte/quotobot/issues" 24 | }, 25 | "homepage": "https://quotobot.js.org", 26 | "devDependencies": { 27 | "eslint": "^8.57.0", 28 | "nodemon": "^3.1.10" 29 | }, 30 | "dependencies": { 31 | "chalk": "^4.1.2", 32 | "country-flag-emoji": "^1.0.3", 33 | "discord.js": "^12.5.3", 34 | "dotenv": "^16.5.0", 35 | "leagueapiwrapper": "^2.5.0", 36 | "lodash": "^4.17.21", 37 | "node-fetch": "^2.7.0", 38 | "spech": "^0.2.1", 39 | "sqlite3": "^5.1.7" 40 | }, 41 | "engines": { 42 | "node": "18.x" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.github/workflows/csv-convert.yml: -------------------------------------------------------------------------------- 1 | name: CSV convert 2 | on: 3 | workflow_dispatch: 4 | jobs: 5 | csv-quote-add: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v3 9 | with: 10 | ref: ${{ github.head_ref }} 11 | - name: Add the new quotes 12 | run: cd db && python3 csvToDB.py 13 | - name: Count the quotes and write it to a YAML file 14 | run: | 15 | cd ./db; COUNT=$(sqlite3 quotes.db "Select Count(*) from Quotes"); echo "count: $COUNT" > quotes.count.yml 16 | - name: Dump the SQLite to a SQL File 17 | run: for i in ./db/*.db; do sqlite3 $i .dump > $i.sql; done 18 | - name: Vacuum the database 19 | run: for i in ./db/*.db; do sqlite3 $i "vacuum;"; done 20 | - name: Dump the SQLite to CSV 21 | run: for i in ./db/*.db; do sqlite3 -header -csv $i "select * from Quotes;" > $i.csv; done 22 | - name: Empty newQuotes.csv 23 | run: true > ./db/newQuotes.csv 24 | - name: Commit the SQLite dumps 25 | uses: stefanzweifel/git-auto-commit-action@1f4914882d31162256a5dd23dd006bf97be303a2 26 | with: 27 | commit_message: SQLite database dump 28 | file_pattern: db/*.db.* db/*.db db/*.yml db/*.csv 29 | - name: Notify if the code is broken 30 | uses: sarisia/actions-status-discord@v1 31 | if: failure() 32 | with: 33 | webhook: ${{ secrets.DISCORD_WEBHOOK }} 34 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies and check the code 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: CI 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | pull_request: 10 | 11 | jobs: 12 | lint: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [lts/*] 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v3 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | - name: Look for JS errors and show how to fix them 27 | run: | 28 | echo -e "\033[0;36m" Installing modules... 29 | npm ci 30 | echo -e "\033[0;36m" Number of quotes: 31 | npm run count 32 | echo -e "\033[0;36m" Installing jsonlint... 33 | sudo npm i -g jsonlint 34 | echo -e "\033[0;36m" Checking for code errors... 35 | for i in *.js db/*.js; do npx eslint $i; npx eslint --fix-dry-run $i; done; for i in *.json; do jsonlint -q $i; done 36 | 37 | # git checkout -b origin/$(git for-each-ref --count=30 --sort=-committerdate refs/heads/ --format='%(refname:short)' | head -1) 38 | # git log | head -1 | sed 's/commit//g' 39 | - name: Notify if the code is broken 40 | uses: sarisia/actions-status-discord@v1 41 | if: failure() 42 | with: 43 | webhook: ${{ secrets.DISCORD_WEBHOOK }} 44 | -------------------------------------------------------------------------------- /img/Logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Pycache 10 | __pycache__/ 11 | 12 | # Diagnostic reports (https://nodejs.org/api/report.html) 13 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 14 | 15 | # Runtime data 16 | pids 17 | *.pid 18 | *.seed 19 | *.pid.lock 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | *.lcov 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # Bower dependency directory (https://bower.io/) 35 | bower_components 36 | 37 | # node-waf configuration 38 | .lock-wscript 39 | 40 | # Compiled binary addons (https://nodejs.org/api/addons.html) 41 | build/Release 42 | 43 | # Dependency directories 44 | node_modules/ 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Microbundle cache 60 | .rpt2_cache/ 61 | .rts2_cache_cjs/ 62 | .rts2_cache_es/ 63 | .rts2_cache_umd/ 64 | 65 | # Optional REPL history 66 | .node_repl_history 67 | 68 | # Output of 'npm pack' 69 | *.tgz 70 | 71 | # Yarn Integrity file 72 | .yarn-integrity 73 | 74 | # dotenv environment variables file 75 | .env 76 | .env.test 77 | 78 | # parcel-bundler cache (https://parceljs.org/) 79 | .cache 80 | 81 | # Next.js build output 82 | .next 83 | 84 | # Nuxt.js build / generate output 85 | .nuxt 86 | dist 87 | 88 | # Gatsby files 89 | .cache/ 90 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 91 | # https://nextjs.org/blog/next-9-1#public-directory-support 92 | # public 93 | 94 | # vuepress build output 95 | .vuepress/dist 96 | 97 | # Serverless directories 98 | .serverless/ 99 | 100 | # FuseBox cache 101 | .fusebox/ 102 | 103 | # DynamoDB Local files 104 | .dynamodb/ 105 | 106 | # TernJS port file 107 | .tern-port 108 | 109 | # Auth file 110 | config.json 111 | 112 | # PNPM and Yarn Lock 113 | pnpm-lock.yaml 114 | yarn.lock 115 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | pull_request: 5 | # The branches below must be a subset of the branches above 6 | branches: [master] 7 | schedule: 8 | - cron: '0 1 * * *' 9 | 10 | jobs: 11 | analyze: 12 | name: Analyze 13 | runs-on: ubuntu-latest 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | # Override automatic language detection by changing the below list 19 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] 20 | language: ['javascript', 'python'] 21 | # Learn more... 22 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 23 | 24 | steps: 25 | - name: Checkout repository 26 | uses: actions/checkout@v3 27 | with: 28 | # We must fetch at least the immediate parents so that if this is 29 | # a pull request then we can checkout the head. 30 | fetch-depth: 2 31 | 32 | # If this run was triggered by a pull request event, then checkout 33 | # the head of the pull request instead of the merge commit. 34 | - run: git checkout HEAD^2 35 | if: ${{ github.event_name == 'pull_request' }} 36 | 37 | # Initializes the CodeQL tools for scanning. 38 | - name: Initialize CodeQL 39 | uses: github/codeql-action/init@v2 40 | with: 41 | languages: ${{ matrix.language }} 42 | # If you wish to specify custom queries, you can do so here or in a config file. 43 | # By default, queries listed here will override any specified in a config file. 44 | # Prefix the list here with "+" to use these queries and those in the config file. 45 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 46 | 47 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 48 | # If this step fails, then you should remove it and run the build manually (see below) 49 | - name: Autobuild 50 | uses: github/codeql-action/autobuild@v2 51 | 52 | # ℹ️ Command-line programs to run using the OS shell. 53 | # 📚 https://git.io/JvXDl 54 | 55 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 56 | # and modify them (or add more) to build your code if your project 57 | # uses a compiled language 58 | 59 | #- run: | 60 | # make bootstrap 61 | # make release 62 | 63 | - name: Perform CodeQL Analysis 64 | uses: github/codeql-action/analyze@v2 65 | - name: Notify if the code is broken 66 | uses: sarisia/actions-status-discord@v1 67 | if: failure() 68 | with: 69 | webhook: ${{ secrets.DISCORD_WEBHOOK }} 70 | -------------------------------------------------------------------------------- /db/portraits.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "George Washington": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Gilbert_Stuart_Williamstown_Portrait_of_George_Washington.jpg", // https://commons.wikimedia.org/wiki/File:Gilbert_Stuart_Williamstown_Portrait_of_George_Washington.jpg 3 | "John Adams": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Gilbert_Stuart,_John_Adams,_c._1800-1815,_NGA_42933.jpg", // https://commons.wikimedia.org/wiki/File:Gilbert_Stuart,_John_Adams,_c._1800-1815,_NGA_42933.jpg 4 | "Thomas Jefferson": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Thomas_Jefferson_by_Rembrandt_Peale,_1800.jpg", // https://commons.wikimedia.org/wiki/File:Thomas_Jefferson_by_Rembrandt_Peale,_1800.jpg 5 | "James Madison": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:James_Madison_(cropped_3x4_close).jpg", // https://commons.wikimedia.org/wiki/File:James_Madison_(cropped_3x4_close).jpg 6 | "*The Scarlet Pimpernel* by Baroness Orczy": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Thescarletpimpernel1908.jpg", // https://commons.wikimedia.org/wiki/File:Thescarletpimpernel1908.jpg 7 | "John F. Kennedy": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:John_F._Kennedy,_White_House_color_photo_portrait.jpg", // https://commons.wikimedia.org/wiki/File:John_F._Kennedy,_White_House_color_photo_portrait.jpg 8 | "Barack Obama": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Official_portrait_of_Barack_Obama.jpg", // https://commons.wikimedia.org/wiki/File:Official_portrait_of_Barack_Obama.jpg 9 | "Alexander Hamilton": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Alexander_Hamilton_portrait_by_John_Trumbull_1806,_detail.jpg", // https://commons.wikimedia.org/wiki/File:Alexander_Hamilton_portrait_by_John_Trumbull_1806.jpg 10 | "Abraham Lincoln": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Abraham_Lincoln_head_on_shoulders_photo_portrait.jpg", // https://commons.wikimedia.org/wiki/File:Abraham_Lincoln_head_on_shoulders_photo_portrait.jpg 11 | "Elon Musk": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Elon_Musk,_2018_(cropped).jpg", // The Royal Society CC BY-SA https://commons.wikimedia.org/wiki/File:Elon_Musk_Royal_Society.jpg 12 | "Eleanor Roosevelt": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Eleanor_Roosevelt_portrait_1933.jpg", // https://commons.wikimedia.org/wiki/File:Eleanor_Roosevelt_portrait_1933.jpg 13 | "QB Devs": "https://raw.githubusercontent.com/Team-Gigabyte/quotobot/master/img/Logo.png", // https://materialdesignicons.com/icon/comment-quote SIL OFL 14 | "Martin Luther King Jr.": "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file&wpvalue=File:Martin_Luther_King,_Jr..jpg", // https://commons.wikimedia.org/wiki/File:Martin_Luther_King,_Jr..jpg 15 | "Anonymous": "https://cdn.discordapp.com/attachments/449680513683292162/771446646327476274/incognito-2231825_1920.png" // by [Nikin](https://pixabay.com/users/nikin-253338/) from [Pixabay](https://pixabay.com/) 16 | } 17 | -------------------------------------------------------------------------------- /wiki/Help.md: -------------------------------------------------------------------------------- 1 | # The Official Guide for Quotobot 2 | ## Use the prefix `~` or mention the bot (the bot works in DMs too) 3 | **How to type `~` (tilde) on US keyboards:** 4 | 5 | ![To get ~, press Shift and grave accent (under the esc key on US keyboards).](https://github.com/Team-Gigabyte/quotobot/raw/master/img/Tilde.png) 6 | ## List of Commands: 7 | (capitalization doesn't matter) 8 | - `randomquote`, `randquote`, `rquote`, `quote`: Prints a random quote 9 | - `shortquote`, `longquote`: Prints a short or long quote respectively. The short quote will be ≤140 characters, and you can click the header to Tweet the quote. 10 | - `ping`: Prints "Pong!" 11 | - `weather`: Gets the weather. All of these commands work, assuming the prefix is `~`: 12 | - `~weather New York` (prints in metric) 13 | - `~weather imperial Mexico City` 14 | - `~weather metric Paris,us` (gets the weather for Paris in the US, not the one in France) 15 | - `~weather Arlington,va,us` (gets the weather for Arlington in Virginia, not the one in Texas) 16 | - You'll need to wait some time between weather queries (at the moment, it's 2 seconds for our host) 17 | - `stock ABCD`, `stocks ABCD`: Pulls up the stock price for whatever stock (in this example, ABCD). 18 | - Note that non-US stocks and CFD indices (such as `^N225`) aren't supported. 19 | - Clicking the title of the bot's message will take you to Yahoo! Finance for that stock. 20 | - You'll need to wait some time between stock queries (at the moment, it's 2 seconds for our host) 21 | - The data and timestamp are not guaranteed to be 100% accurate, so don't trade based on the info the bot returns. 22 | - `amiadmin`: Returns if you have the administrator permission in the current server. (Doesn't work in a DM, although you can try.) 23 | - `league`, `lol`, `lolstats` or `leaguestats`: Returns some stats for a certain League user. For example, assuming the prefix is `~`: 24 | - `~leaguestats ExampleSummoner JP` (JP is equivalent to jp1) 25 | - `~leaguestats Some1234Summoner` (defaults to NA) 26 | - `~leaguestats Multiworded+summoner` (looks up `Multiworded summoner`) 27 | - You'll need to wait some time between League queries (at the moment, it's 5 seconds for our host) 28 | 29 | 30 | 31 | | Region | Equivalent to (the bot doesn't accept these) | 32 | |:--------:|---------------| 33 | | KR | | 34 | | BR1 | | 35 | | OCE | oc1 | 36 | | JP | jp1 | 37 | | NA | na1 | 38 | | EUNE | eun1 | 39 | | EUW | euw1 | 40 | | TR | tr1 | 41 | | LAN | la1 | 42 | | LAS | la2 | 43 | | RU | | 44 | 45 | - `help`: Brings up a hyperlink to this commands list 46 | 47 | - `spellcheck`: Returns all the spelling mistakes in the text following this command and suggestions for what the correct word may be. 48 | - Example, assuming the prefix is `~`: `~spellcheck helo ther, this is realy mispeled.` 49 | - There's a limit of 500 characters. 50 | - Currently this command only supports English (United States). Leave a GitHub issue if you want to see another language in the future. 51 | 52 | ## Are the messages blank? 53 | If Quotobot's messages appear blank, you may have embeds off. Fix it by going to Discord Settings → Text and Images → Show embeds and preview website links pasted into chat. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Quotobot

2 |

(KWO-toe-bot)
An open source Discord bot that displays 200+ hand-curated quotes, tells you the weather, fetches stock and League info, and more!
3 |

4 |

5 | 6 | [![Invite Quotobot to your server](https://img.shields.io/static/v1?label=Invite%20to&message=your%20server&color=3a57c1&logo=Discord&style=for-the-badge&logoColor=white)][inv] 7 | [![View the command list](https://img.shields.io/badge/%E2%9D%94%20Help%20and-Command%20List-347534?style=for-the-badge)](../../wiki/Help) 8 | [![Number of quotes](https://img.shields.io/badge/dynamic/yaml?color=c13a3a&label=quotes&query=%24.count&url=https%3A%2F%2Fraw.githubusercontent.com%2FTeam-Gigabyte%2Fquotobot%2Fmaster%2Fdb%2Fquotes.count.yml&style=for-the-badge)](https://github.com/Team-Gigabyte/quotobot/blob/master/db/quotes.db.csv) 9 | 10 | ![Quotes screenshot](https://raw.githubusercontent.com/Team-Gigabyte/quotobot/master/img/Demo%20Picture.png) 11 | 12 | ![Weather screenshot](https://raw.githubusercontent.com/Team-Gigabyte/quotobot/master/img/Weather%20Demo.png) 13 | 14 | ![Stock screenshot](https://raw.githubusercontent.com/Team-Gigabyte/quotobot/master/img/Stock%20Demo.png) 15 | 16 | 17 | # 🤖 [INVITE THE BOT TO YOUR SERVER!][inv] 18 | ## 🤔 [Need to see a list of commands? Click here.](../../wiki/Help) ([Alternate Link](https://github.com/Team-Gigabyte/quotobot/wiki/Help)) 19 | ## 👨‍💻 [Do you want to host and tweak the bot yourself? Click here.](../../wiki/Hosting) ([Alternate Link](https://github.com/Team-Gigabyte/quotobot/wiki/Hosting)) 20 | 21 | [![top.gg stats](https://top.gg/api/widget/746889272992464958.svg)](https://top.gg/bot/746889272992464958) 22 | 23 | # Technical Notes 24 | ![Built with JS](https://img.shields.io/static/v1?label=built%20with&message=JS&color=yellow&logo=javascript) 25 | ![CI](https://github.com/Team-Gigabyte/quotobot/workflows/CI/badge.svg) 26 | [![DeepScan grade](https://deepscan.io/api/teams/10906/projects/13838/branches/243095/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=10906&pid=13838&bid=243095) 27 | [![DeepSource](https://deepsource.io/gh/Team-Gigabyte/quotobot.svg/?label=active+issues)](https://deepsource.io/gh/Team-Gigabyte/quotobot/?ref=repository-badge) 28 | [![GitHub license](https://img.shields.io/github/license/Team-Gigabyte/quotobot)](https://github.com/Team-Gigabyte/quotobot/blob/master/LICENSE) 29 | [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Team-Gigabyte/quotobot?logo=github&sort=semver)](https://github.com/Team-Gigabyte/quotobot/releases/latest) 30 | 31 | This bot mainly uses Node.js and Discord.js. The quotes are stored in an SQLite database and accessed using the `sqlite3` module. The weather comes from [OpenWeatherMap](https://openweathermap.org/), stock data comes from [Finnhub](https://finnhub.io/), and League stats come from the [official Riot API](https://developer.riotgames.com/). (If you want to see the quotes without using SQLite, take a look at the [quotes.db.csv](./db/quotes.db.csv) file.) 32 | 33 | # Acknowledgements 34 | Thank you to: 35 | * [Uddesh](https://github.com/UddeshJain). We used part of his [weather bot code](https://github.com/UddeshJain/Discord-Weather-Bot) and modified it for our project. 36 | * The maintainers of all the open source NPM packages we use. 37 | * Riot Games, for approving our API key. 38 | * This bot isn't endorsed by Riot Games and doesn't reflect the views or opinions of Riot Games or anyone officially involved in producing or managing Riot Games properties. Riot Games, and all associated properties are trademarks or registered trademarks of Riot Games, Inc. 39 | * The OpenWeatherMap and Finnhub APIs, which power some of the bot functions. 40 | * [Material Design Icons](https://materialdesignicons.com/), for the quote icon we used to make the bot's logo. 41 | * All the original photographers of the quote author pictures used. All required credits are in [`db/portraits.js`](/db/portraits.js). 42 | * All the contributors to this project. 43 | * Every person who said the quotes in our database. 44 | * Inclusion of a person's quotes in our database does not imply our endorsement of said person's opinions. 45 | 46 | # Contribute 47 | Any pull requests are appreciated. If you want to add quotes, you can follow [the quote-adding process](https://github.com/Team-Gigabyte/quotobot/wiki/Hosting#bulk-csv-method-recommended) on a fork, but only do step 1 and submit the pull request. Or, if you have problems with that process, open a GitHub issue with the quote, author, and a source (website that has the quote). 48 | # License 49 | This project is licensed under the [MIT](https://github.com/Team-Gigabyte/quotobot/blob/master/LICENSE) license. You can use it for pretty much anything as long as you credit us. 50 | However, if you use the quotes from our database, you must put credit in the same place where you display the quote. 51 | # Donate? 52 | [![Donate today](https://img.shields.io/static/v1?label=donate&message=today&color=green)](https://github.com/Team-Gigabyte/donate) 53 | 54 | Thank you for reading to the end. If you learned something from the bot, or have enjoyed using it, please consider donating [here](https://github.com/Team-Gigabyte/donate). All donations help us continue maintain this, which we have spent countless hours working on. **Thank you!** 55 | 56 |
57 | 58 | 66 |
67 | 68 | [inv]: https://discord.com/oauth2/authorize?client_id=746889272992464958&permissions=280576&scope=bot 69 | -------------------------------------------------------------------------------- /wiki/Hosting.md: -------------------------------------------------------------------------------- 1 | # How To Host Quotobot 2 | Advanced users not using Docker should use the [environment variable setup](#environment-variables-instead-of-configjson). 3 | ## How to set up the config.json 4 | - Make a copy of config-example.json and call it config.json. 5 | 6 | - Delete the entire line with `"instructions"` if you want to. 7 | 8 | - Change the prefix if you like (keep it inside the quotes). 9 | 10 | - **Where it says `"your-token-here"`, paste in your Discord bot token (also inside the quotes).** 11 | 12 | - If you want the bot to output its invite link on startup, change 13 | ```json 14 | "clientID-example": "123456789012347", 15 | ``` 16 | to 17 | ```json 18 | "clientID": "123456789012347", 19 | ``` 20 | 21 | making sure to change the number to your client ID inside the quotes. 22 |
23 | 24 | More info about the APIs. 25 | 26 | You can add an [OpenWeatherMap API key](https://openweathermap.org/guide#how), [Finnhub (stocks) key](https://finnhub.io), and a [Riot key](https://developer.riotgames.com/) in the same way. OpenWeatherMap and Finnhub are free and easy to get, but Riot needs you to submit an application to get a key. If any of these keys are missing, the bot won't crash – it'll just let the user know that the feature isn't working if they try to use it. 27 |
28 | 29 | You can also change the status that the bot shows (it'll be prefixed with *Watching*, though) by changing the `help-domain-example` to `help-domain` (which will also be used by the Share to Twitter link) and adding your text in the value for that. Example complete config file: 30 | ```json 31 | { 32 | "prefix": "&&", 33 | "token": "abcdrkhjregjl.efghfioeigtj", 34 | "help-domain": "my-bot-site.qb", 35 | "clientID": "12343546798", 36 | "permissionValue": 0, 37 | "weather-token": "1jf920fk3", 38 | "weatherTimeout": 2000, 39 | "stockToken": "FinnhubKey92323032", 40 | "stockTimeout": 2000, 41 | "riotKey": "RGAPI-199020190912091", 42 | "leagueTimeout": 3000 43 | } 44 | ``` 45 | The timeouts are optional and set in milliseconds. 46 | ## Environment Variables instead of `config.json` 47 | Instead of using the config.json, you can set environment variables. See [the .env.example file](./.env.example) for the variable names and details. 48 | 49 | You can also use a .env file to set environment variables. Just copy the lines you want to use (lines starting with `#` are ignored) into a file in this same folder called `.env`. If you use this method, don't keep a `config.json` file in the same folder. 50 | 51 | Note that there is currently no way to change stuff like the client ID this way. 52 | ## Run the bot 53 | Make sure you have [the latest LTS version of Node.js](https://nodejs.org/) installed and open a command prompt/terminal in the folder where these files are. Then run: 54 | ```bash 55 | npm install 56 | node index.js 57 | ``` 58 | Press Control + C (even on a Mac) to stop the bot. 59 | ## Run as a Docker container 60 | - [Do the config.json stuff listed above.](#how-to-set-up-the-configjson) 61 | - Build the image: 62 | ``` 63 | docker build -t quotobot/quotobot . 64 | ``` 65 | - Run this command to start the container: 66 | ``` 67 | docker run --name quotobot1 -d -v ./config.json:/app/config.json quotobot/quotobot 68 | ``` 69 | Note that the Dockerfile hasn't been tested so far. 70 | ## Heroku notes 71 | For Heroku, use the [environment variables setup](#environment-variables-instead-of-configjson) (it's called *config vars* in Heroku). You'll probably need to turn off the web dyno and turn on the worker dyno. 72 | ## Keeping your copy up to date 73 | If you used the `git clone` command to download the bot, just do 74 | ```bash 75 | git pull origin 76 | ``` 77 | to update. If you want to switch to the version you had before, you can use 78 | ```bash 79 | git checkout tags/v2.1.2 80 | ``` 81 | and replace 2.1.2 with whatever [version](https://github.com/Team-Gigabyte/quotobot/releases) you want. Then, to switch back to the latest code, use 82 | ```bash 83 | git checkout master 84 | ``` 85 | We follow semver, so as long as the first number in the version number is the same as your old release, you shouldn't have to change anything to make the new release work. 86 | ## Adding quotes 87 | - Don't modify anything in the quotes.db.csv or the .sql files, since those are auto-generated dumps. 88 | ### Bulk CSV method (recommended) 89 | You can do all of this from the GitHub web interface. 90 | 1. Put your quotes in db/newQuotes.csv (the first column has the quote, the second is the author). Make sure the first column doesn't say what the columns are. 91 | - Make sure to not put a space between the fields. 92 | ```csv 93 | "This is wrong.", "Example Person" 94 | "This is right.","Example Person" 95 | ``` 96 | 2. Go [here](https://github.com/Team-Gigabyte/quotobot/actions?query=workflow%3A%22CSV+convert%22) (link will be different if you're working on a fork) and click Run Workflow. Use the workflow from the master branch. 97 | 3. After that's done (assuming there aren't any errors), check if the quotes are in db/quotes.db.csv. If they are, get rid of the quotes in newQuotes.csv. 98 | ### JS method (not recommended; sometimes doesn't work) 99 |
100 | 101 | Click here to see instructions. 102 | 103 | 104 | - Use the addQuote.js script, which will prompt you for the required info and add it to db/quotes.db. 105 | - Make sure to make your quotes the *last* commits before you push, otherwise you'll get merge conflicts. 106 | You can also take a look at the csvToDb.py file and experiment with that. (You'll need Python and SQLite for that, and you need to modify the file name in the script.) 107 | 108 |
109 | -------------------------------------------------------------------------------- /db/quotes.db.csv: -------------------------------------------------------------------------------- 1 | quote,id,source,usage 2 | "Never put off till to-morrow what you can do to-day.",1,"Thomas Jefferson",0 3 | "Never trouble another for what you can do yourself. ",2,"Thomas Jefferson",0 4 | "Never spend your money before you have it.",3,"Thomas Jefferson",0 5 | "Never buy what you do not want, because it is cheap; it will be dear to you.",4,"Thomas Jefferson",0 6 | "Pride costs us more than hunger, thirst, and cold.",5,"Thomas Jefferson",0 7 | "We never repent of having eaten too little.",6,"Thomas Jefferson",0 8 | "Nothing is troublesome that we do willingly.",7,"Thomas Jefferson",0 9 | "How much pain have cost us the evils which have never happened.",8,"Thomas Jefferson",0 10 | "Take things always by their smooth handle.",9,"Thomas Jefferson",0 11 | "When angry, count ten, before you speak; if very angry, a hundred.",10,"Thomas Jefferson",0 12 | "It is better to offer no excuse than a bad one. ",11,"George Washington",0 13 | "It is better to be alone than in bad company. ",12,"George Washington",0 14 | "If freedom of speech is taken away, then dumb and silent we may be led, like sheep to the slaughter.",13,"George Washington",0 15 | "But lest some unlucky event should happen unfavorable to my reputation, I beg it may be remembered by every gentleman in the room that I this day declare with the utmost sincerity, I do not think myself equal to the command I am honored with.",14,"George Washington",0 16 | "A primary object should be the education of our youth in the science of government. In a republic, what species of knowledge can be equally important? And what duty more pressing than communicating it to those who are to be the future guardians of the liberties of the country?",15,"George Washington",0 17 | "Be courteous to all, but intimate with few, and let those few be well tried before you give them your confidence. True friendship is a plant of slow growth, and must undergo and withstand the shocks of adversity before it is entitled to appellation.",16,"George Washington",1 18 | "A free people ought not only to be armed, but disciplined; to which end a uniform and well-digested plan is requisite; and their safety and interest require that they should promote such manufactories as tend to render them independent of others for essential, particularly military, supplies.",17,"George Washington",0 19 | "Human happiness and moral duty are inseparably connected.",18,"George Washington",0 20 | "However [political parties] may now and then answer popular ends, they are likely in the course of time and things, to become potent engines, by which cunning, ambitious, and unprincipled men will be enabled to subvert the power of the people and to usurp for themselves the reins of government, destroying afterwards the very engines which have lifted them to unjust dominion.",19,"George Washington",0 21 | "99% of failures come from people who make excuses.",20,"George Washington",0 22 | "Guard against the impostures of pretended patriotism.",21,"George Washington",0 23 | "Labor to keep alive in your breast that little spark of celestial fire called conscience.",22,"George Washington",0 24 | "Perseverance and spirit have done wonders in all ages.",23,"George Washington",0 25 | "Associate yourself with men of good quality, if you esteem your own reputation; for ‘tis better to be alone than in bad company.",24,"George Washington",0 26 | "Few men have virtue to withstand the highest bidder.",25,"George Washington",0 27 | "Happiness depends more upon the internal frame of a person’s own mind, than on the externals in the world.",26,"George Washington",0 28 | "Experience teaches us that it is much easier to prevent an enemy from posting themselves than it is to dislodge them after they have got possession. ",27,"George Washington",0 29 | "The harder the conflict, the greater the triumph",28,"George Washington",0 30 | "Worry is the interest paid by those who borrow trouble.",29,"George Washington",0 31 | "The turning points of lives are not the great moments. The real crises are often concealed in occurrences so trivial in appearance that they pass unobserved.",30,"George Washington",0 32 | "Real men despise battle, but will never run from it.",31,"George Washington",0 33 | "Discipline is the soul of an army. It makes small numbers formidable; procures success to the weak, and esteem to all.",32,"George Washington",0 34 | "Citizens by birth or choice of a common country, that country has a right to concentrate your affections. The name of American, which belongs to you, in your national capacity, must always exalt the just pride of Patriotism, more than any appellation derived from local discriminations.",33,"George Washington",0 35 | "We should not look back unless it is to derive useful lessons from past errors, and for the purpose of profiting by dearly bought experience.",34,"George Washington",0 36 | "I read my eyes out and can't read half enough...the more one reads the more one sees we have to read.",35,"John Adams",0 37 | "Let us tenderly and kindly cherish therefore, the means of knowledge. Let us dare to read, think, speak, and write.",36,"John Adams",0 38 | "Facts are stubborn things; and whatever may be our wishes, our inclinations, or the dictates of our passion, they cannot alter the state of facts and evidence.",37,"John Adams",0 39 | "A Constitution of Government once changed from Freedom, can never be restored. Liberty, once lost, is lost forever.",38,"John Adams",0 40 | "The longer I live, the more I read, the more patiently I think, and the more anxiously I inquire, the less I seem to know...Do justly. Love mercy. Walk humbly. This is enough.",39,"John Adams",0 41 | "There is nothing which I dread so much as a division of the republic into two great parties, each arranged under its leader, and concerting measures in opposition to each other. This, in my humble apprehension, is to be dreaded as the greatest political evil under our Constitution.",40,"John Adams",0 42 | "Posterity! you will never know how much it cost the present generation to preserve your freedom! I hope you will make a good use of it.",41,"John Adams",0 43 | "I say, that Power must never be trusted without a check.",42,"John Adams",0 44 | "Children should be educated and instructed in the principles of freedom. Aristotle speaks plainly to this purpose, saying, 'that the institution of youth should be accommodated to that form of government under which they live; forasmuch as it makes exceedingly for the preservation of the present government, whatsoever it be.",43,"John Adams",0 45 | "Let the human mind loose. It must be loose. It will be loose. Superstition and dogmatism cannot confine it.",44,"John Adams",0 46 | "I must judge for myself, but how can I judge, how can any man judge, unless his mind has been opened and enlarged by reading.",45,"John Adams",0 47 | "To believe all men honest is folly. To believe none is something worse.",46,"John Adams",1 48 | "Government has no right to hurt a hair on the head of an Atheist for his Opinions. Let him have a care of his Practices.",47,"John Adams",0 49 | "You will never be alone with a poet in your pocket.",48,"John Adams",0 50 | "The way to secure liberty is to place it in the people's hands, that is, to give them the power at all times to defend it in the legislature and in the courts of justice.",49,"John Adams",0 51 | "There is danger from all men. The only maxim of a free government ought to be to trust no man living with power to endanger the public liberty.",50,"John Adams",0 52 | "The happiness of society is the end of government.",51,"John Adams",0 53 | "Be not intimidated...nor suffer yourselves to be wheedled out of your liberties by any pretense of politeness, delicacy, or decency. These, as they are often used, are but three different names for hypocrisy, chicanery and cowardice.",52,"John Adams",0 54 | "And liberty cannot be preserved without a general knowledge among the people who have a right from the frame of their nature to knowledge...",53,"John Adams",0 55 | "Without the pen of Paine, the sword of Washington would have been wielded in vain.",54,"John Adams",0 56 | "Laws for the liberal education of youth, especially of the lower class of people, are so extremely wise and useful, that, to a humane and generous mind, no expense for this purpose would be thought extravagant.",55,"John Adams",0 57 | "Old minds are like old horses; you must exercise them if you wish to keep them in working order.",56,"John Adams",0 58 | "Nineteen twentieths of [mankind is] opaque and unenlightened. Intimacy with most people will make you acquainted with vices and errors and follies enough to make you despise them.",57,"John Adams",0 59 | "If worthless men are sometimes at the head of affairs, it is, I believe, because worthless men are at the tail and the middle",58,"John Adams",1 60 | "When legislature is corrupted, the people are undone.",59,"John Adams",0 61 | "The true source of our sufferings has been our timidity.",60,"John Adams",0 62 | "Everything in life should be done with reflection.",61,"John Adams",0 63 | "Great is the guilt of an unnecessary war.",62,"John Adams",0 64 | "The jaws of power are always open to devour, and her arm is always stretched out, if possible, to destroy the freedom of thinking, speaking, and writing.",63,"John Adams",0 65 | "Abuse of words has been the great instrument of sophistry and chicanery, of party, faction, and division of society.",64,"John Adams",0 66 | "Property monopolized or in the possession of a few is a curse to mankind.",65,"John Adams",0 67 | "Work smarter, not harder — something we should've followed more when making this.",66,"QB Devs",0 68 | "Always make sure you know what work the other people in a group project will do before starting work on the project.",67,"QB Devs",0 69 | "He seemed so devoted — a very slave — and there was a certain latent intensity in that love which had fascinated her.",68,"*The Scarlet Pimpernel* by Baroness Orczy",0 70 | "Thus human beings judge of one another, superficially, casually, throwing contempt on one another, with but little reason, and no charity.",69,"*The Scarlet Pimpernel* by Baroness Orczy",0 71 | "He was calmly eating his soup, laughing with pleasant good-humour, as if he had come all the way to Calais for the express purpose of enjoying supper at this filthy inn, in the company of his arch-enemy.",70,"*The Scarlet Pimpernel* by Baroness Orczy",0 72 | "Those friends who knew, laughed to scorn the idea that Marguerite St. Just had married a fool for the sake of the worldly advantages with which he might endow her. They knew, as a matter of fact, that Marguerite St. Just cared nothing about money, and still less about a title.",71,"*The Scarlet Pimpernel* by Baroness Orczy",0 73 | """Money and titles may be hereditary,"" she would say, ""but brains are not.""",72,"*The Scarlet Pimpernel* by Baroness Orczy",0 74 | "We seek him here, we seek him there, Those Frenchies seek him everywhere. Is he in heaven? — Is he in hell? That demmed, elusive Pimpernel?",73,"*The Scarlet Pimpernel* by Baroness Orczy",0 75 | "How that stupid, dull Englishman ever came to be admitted within the intellectual circle which revolved round “the cleverest woman in Europe,” as her friends unanimously called her, no one ventured to guess—a golden key is said to open every door, asserted the more malignantly inclined.",74,"*The Scarlet Pimpernel* by Baroness Orczy",0 76 | "This is an example.",75,"QB Devs",0 77 | "Ask not what your country can do for you; ask what you can do for your country.",76,"John F. Kennedy",0 78 | "If not us, who? If not now, when?",77,"John F. Kennedy",0 79 | "Every accomplishment starts with the decision to try.",78,"John F. Kennedy",0 80 | "As we express our gratitude, we must never forget that the highest form of appreciation is not to utter words, but to live by them.",79,"John F. Kennedy",0 81 | "Those who dare to fail miserably can achieve greatly.",80,"John F. Kennedy",0 82 | "The ignorance of one voter in a democracy impairs the security of all.",81,"John F. Kennedy",0 83 | "Do not pray for easy lives, pray to be stronger men.",82,"John F. Kennedy",0 84 | "Leadership and learning are indispensable to each other.",83,"John F. Kennedy",0 85 | "Life is never easy. There is work to be done and obligations to be met—obligations to truth, to justice, and to liberty.",84,"John F. Kennedy",0 86 | "Too often we enjoy the comfort of opinion without the discomfort of thought.",85,"John F. Kennedy",0 87 | "We have the power to make this the best generation of mankind in the history of the world or make it the last.",86,"John F. Kennedy",0 88 | "The greater our knowledge increases the more our ignorance unfolds.",87,"John F. Kennedy",0 89 | "There's not a liberal America and a conservative America — there's the United States of America.",88,"Barack Obama",0 90 | "Change will not come if we wait for some other person or if we wait for some other time. We are the ones we've been waiting for. We are the change that we seek.",89,"Barack Obama",0 91 | "Where we are met with cynicism and doubts and those who tell us that we can't, we will respond with that timeless creed that sums up the spirit of a people: Yes, we can.",90,"Barack Obama",0 92 | "Clear-eyed, we can understand that there will be war, and still strive for peace.",91,"Barack Obama",0 93 | "With eyes fixed on the horizon and God's grace upon us, we carried forth that great gift of freedom and delivered it safely to future generations.",92,"Barack Obama",0 94 | "There has been one constant amidst these shifting tides. At every turn, America's men and women in uniform have served with courage and resolve.",93,"Barack Obama",0 95 | "We should do everything we can to make sure this country lives up to our children's expectations.",94,"Barack Obama",0 96 | "As it has for more than two centuries, progress will come in fits and starts. It's not always a straight line. It's not always a smooth path.",95,"Barack Obama",0 97 | "The strongest weapon against hateful speech is not repression; it is more speech.",96,"Barack Obama",0 98 | "The cynics may be the loudest voices, — but I promise you, they will accomplish the least.",97,"Barack Obama",0 99 | "We choose hope over fear. We see the future not as something out of our control, but as something we can shape for the better through concerted and collective effort.",98,"Barack Obama",0 100 | "To be an American is about something more than what we look like, or what our last names are, or how we worship.",99,"Barack Obama",0 101 | "It is you, the young and fearless at heart, the most diverse and educated generation in our history, who the nation is waiting to follow.",100,"Barack Obama",0 102 | "No matter who you are or what you look like, how you started off, or how and who you love, America is a place where you can write your own destiny.",101,"Barack Obama",0 103 | "That's the America I know. That's the country we love. Clear-eyed. Big-hearted. Undaunted by challenge.",102,"Barack Obama",0 104 | "The long sweep of America has been defined by forward motion, a constant widening of our founding creed to embrace all and not just some.",103,"Barack Obama",0 105 | "To quote or not to quote, that is the question.",104,"QB Devs",0 106 | "You can’t let your failures define you. You have to let your failures teach you.",105,"Barack Obama",0 107 | "Men give me credit for some genius. All the genius I have lies in this; when I have a subject in hand, I study it profoundly. Day and night it is before me. My mind becomes pervaded with it. Then the effort that I have made is what people are pleased to call the fruit of genius. It is the fruit of labor and thought.",106,"Alexander Hamilton",0 108 | "Those who stand for nothing fall for everything.",107,"Alexander Hamilton",0 109 | "Give all the power to the many, they will oppress the few. Give all the power to the few, they will oppress the many.",108,"Alexander Hamilton",0 110 | "The constitution shall never be construed...to prevent the people of the United States who are peaceable citizens from keeping their own arms.",109,"Alexander Hamilton",0 111 | "A well adjusted person is one who makes the same mistake twice without getting nervous.",110,"Alexander Hamilton",0 112 | "The art of reading is to skip judiciously.",111,"Alexander Hamilton",0 113 | "I never expect a perfect work from an imperfect man.",112,"Alexander Hamilton",0 114 | "A nation which can prefer disgrace to danger is prepared for a master, and deserves one.",113,"Alexander Hamilton",0 115 | "There are seasons in every country when noise and impudence pass current for worth; and in popular commotions especially, the clamors of interested and factious men are often mistaken for patriotism.",114,"Alexander Hamilton",0 116 | "The sacred rights of mankind are not to be rummaged for among old parchments or musty records. They are written, as with a sunbeam, in the whole volume of human nature, by the Hand of Divinity itself, and can never be erased or obscured by mortal power.",115,"Alexander Hamilton",0 117 | "Hard words are very rarely useful. Real firmness is good for every thing. Strut is good for nothing.",116,"Alexander Hamilton",0 118 | "I have thought it my duty to exhibit things as they are, not as they ought to be.",117,"Alexander Hamilton",0 119 | "Men are reasoning rather than reasonable animals.",118,"Alexander Hamilton",0 120 | "Who talks most about freedom and equality? Is it not those who hold the bill of rights in one hand and a whip for affrighted slaves in the other?",119,"Alexander Hamilton",0 121 | "The best we can hope for concerning the people at large is that they be properly armed.",120,"Alexander Hamilton",0 122 | "A powerful, victorious ally is yet another name for master.",121,"Alexander Hamilton",0 123 | "For in politics, as in religion, it is equally absurd to aim at making proselytes by fire and sword. Heresies in either can rarely be cured by persecution.",122,"Alexander Hamilton",0 124 | "If we must have an enemy at the head of government, let it be one whom we can oppose, and for whom we are not responsible.",123,"Alexander Hamilton",0 125 | "Vigor of government is essential to the security of liberty.",124,"Alexander Hamilton",0 126 | "It will be of little avail to the people, that the laws are made by men of their own choice, if the laws be so voluminous that they cannot be read, or so incoherent that they cannot be understood",125,"Alexander Hamilton",0 127 | "The inquiry constantly is what will please, not what will benefit the people. In such a government there can be nothing but temporary expedient, fickleness, and folly.",126,"Alexander Hamilton",0 128 | "The mark of a pro coder is `Build Passing`",127,"QB Devs",0 129 | "If a teacher gives you several days for an assignment, there is a reason for that; there is a lot of work.",128,"QB Devs",0 130 | "Folks are usually about as happy as they make their minds up to be.",129,"Abraham Lincoln",0 131 | "Whatever you are, be a good one.",130,"Abraham Lincoln",0 132 | "Do I not destroy my enemies when I make them my friends?",131,"Abraham Lincoln",0 133 | "America will never be destroyed from the outside. If we falter and lose our freedoms, it will be because we destroyed ourselves.",132,"Abraham Lincoln",0 134 | "My Best Friend is a person who will give me a book I have not read.",133,"Abraham Lincoln",0 135 | "Nearly all men can stand adversity, but if you want to test a man's character, give him power.",134,"Abraham Lincoln",0 136 | "I'm a success today because I had a friend who believed in me and I didn't have the heart to let him down.",135,"Abraham Lincoln",0 137 | "Books serve to show a man that those original thoughts of his aren't very new after all.",136,"Abraham Lincoln",0 138 | "Those who deny freedom to others, deserve it not for themselves.",137,"Abraham Lincoln",0 139 | "Whenever I hear anyone arguing for slavery, I feel a strong impulse to see it tried on him personally.",138,"Abraham Lincoln",0 140 | "Those who look for the bad in people will surely find it.",139,"Abraham Lincoln",0 141 | "I am not bound to win, but I am bound to be true. I am not bound to succeed, but I am bound to live up to what light I have.",140,"Abraham Lincoln",0 142 | "Be sure you put your feet in the right place, then stand firm.",141,"Abraham Lincoln",0 143 | "You can fool some of the people all of the time, and all of the people some of the time, but you can not fool all of the people all of the time.",142,"Abraham Lincoln",0 144 | "I would rather be a little nobody than to be [an] evil somebody.",143,"Abraham Lincoln",0 145 | "Character is like a tree and reputation its shadow. The shadow is what we think it is and the tree is the real thing.",144,"Abraham Lincoln",0 146 | "Always bear in mind that your own resolution to succeed is more important than any one thing.",145,"Abraham Lincoln",0 147 | "The best way to predict your future is to create it.",146,"Abraham Lincoln",0 148 | "Elections belong to the people. It's their decision. If they decide to turn their back on the fire and burn their behinds, then they will just have to sit on their blisters.",147,"Abraham Lincoln",0 149 | "Give me six hours to chop down a tree and I will spend the first four sharpening the axe.",148,"Abraham Lincoln",0 150 | "No man has a good enough memory to be a successful liar.",149,"Abraham Lincoln",0 151 | "The best thing about the future is that it comes one day at a time.",150,"Abraham Lincoln",0 152 | "I have always found that mercy bears richer fruits than strict justice.",151,"Abraham Lincoln",0 153 | "I care not for a man's religion whose dog and cat are not the better for it.",152,"Abraham Lincoln",0 154 | "You cannot escape the responsibility of tomorrow by evading it today.",153,"Abraham Lincoln",0 155 | "I do not think much of a man who is not wiser today than he was yesterday.",154,"Abraham Lincoln",0 156 | "You have to do your own growing no matter how tall your grandfather was.",155,"Abraham Lincoln",0 157 | "You cannot help people permanently by doing for them, what they could and should do for themselves.",156,"Abraham Lincoln",0 158 | "You can tell the greatness of a man by what makes him angry.",157,"Abraham Lincoln",0 159 | "When something is important enough, you do it even if the odds are not in your favor.",158,"Elon Musk",0 160 | "If you get up in the morning and think the future is going to be better, it is a bright day. Otherwise, it's not.",159,"Elon Musk",0 161 | "There have to be reasons that you get up in the morning and you want to live. Why do you want to live? What's the point? What inspires you? What do you love about the future? If the future does not include being out there among the stars and being a multi-planet species, I find that incredibly depressing.",160,"Elon Musk",0 162 | "When Henry Ford made cheap, reliable cars, people said, 'Nah, what's wrong with a horse?' That was a huge bet he made, and it worked.",161,"Elon Musk",0 163 | "Persistence is very important. You should not give up unless you are forced to give up.",162,"Elon Musk",0 164 | "It's OK to have your eggs in one basket as long as you control what happens to that basket.",163,"Elon Musk",0 165 | "If you go back a few hundred years, what we take for granted today would seem like magic-being able to talk to people over long distances, to transmit images, flying, accessing vast amounts of data like an oracle. These are all things that would have been considered magic a few hundred years ago.",164,"Elon Musk",0 166 | "The first step is to establish that something is possible; then probability will occur.",165,"Elon Musk",0 167 | "I think it is possible for ordinary people to choose to be extraordinary.",166,"Elon Musk",0 168 | "I could either watch it happen or be a part of it.",167,"Elon Musk",0 169 | "Do one thing every day that scares you.",168,"Eleanor Roosevelt",0 170 | "Do what you feel in your heart to be right – for you’ll be criticized anyway.",169,"Eleanor Roosevelt",0 171 | "The future belongs to those who believe in the beauty of their dreams.",170,"Eleanor Roosevelt",0 172 | "The purpose of life is to live it, to taste experience to the utmost, to reach out eagerly and without fear for newer and richer experience.",171,"Eleanor Roosevelt",0 173 | "Many people will walk in and out of your life, but only true friends will leave footprints in your heart.",172,"Eleanor Roosevelt",0 174 | "We are afraid to care too much, for fear that the other person does not care at all.",173,"Eleanor Roosevelt",0 175 | "To handle yourself, use your head; to handle others, use your heart.",174,"Eleanor Roosevelt",0 176 | "You can often change your circumstances by changing your attitude.",175,"Eleanor Roosevelt",0 177 | "If someone betrays you once, it’s their fault; if they betray you twice, it’s your fault.",176,"Eleanor Roosevelt",0 178 | "With the new day comes new strength and new thoughts.",177,"Eleanor Roosevelt",0 179 | "Happiness is not a goal...it's a by-product of a life well lived.",178,"Eleanor Roosevelt",0 180 | "Life was meant to be lived, and curiosity must be kept alive. One must never, for whatever reason, turn his back on life.",179,"Eleanor Roosevelt",0 181 | "It is not fair to ask of others what you are not willing to do yourself.",180,"Eleanor Roosevelt",0 182 | "You have to accept whatever comes, and the only important thing is that you meet it with the best you have to give.",181,"Eleanor Roosevelt",0 183 | "In the long run, we shape our lives, and we shape ourselves. The process never ends until we die. And the choices we make are ultimately our own responsibility.",182,"Eleanor Roosevelt",0 184 | "Friendship with oneself is all important, because without it one cannot be friends with anyone else in the world.",183,"Eleanor Roosevelt",0 185 | "Never allow a person to tell you no who doesn't have the power to say yes.",184,"Eleanor Roosevelt",0 186 | "Never mistake knowledge for wisdom. One helps you make a living; the other helps you make a life.",185,"Eleanor Roosevelt",0 187 | "No one won the last war, and no one will win the next war.",186,"Eleanor Roosevelt",0 188 | "When will our consciences grow so tender that we will act to prevent human misery rather than avenge it?",187,"Eleanor Roosevelt",0 189 | "We are not makers of history. We are made by history.",188,"Martin Luther King Jr.",0 190 | "Every man must decide whether he will walk in the light of creative altruism or in the darkness of destructive selfishness.",189,"Martin Luther King Jr.",0 191 | "We must use time creatively, in the knowledge that the time is always ripe to do right.",190,"Martin Luther King Jr.",0 192 | "There is nothing more tragic than to find an individual bogged down in the length of life, devoid of breadth.",191,"Martin Luther King Jr.",0 193 | "Property is intended to serve life, and no matter how much we surround it with rights and respect, it has no personal being. It is part of the earth man walks on. It is not man.",192,"Martin Luther King Jr.",0 194 | "The function of education is to teach one to think intensively and to think critically. Intelligence plus character – that is the goal of true education.",193,"Martin Luther King Jr.",0 195 | "All labor that uplifts humanity has dignity and importance and should be undertaken with painstaking excellence.",194,"Martin Luther King Jr.",0 196 | "An individual has not started living until he can rise above the narrow confines of his individualistic concerns to the broader concerns of all humanity.",195,"Martin Luther King Jr.",0 197 | "Rarely do we find men who willingly engage in hard, solid thinking. There is an almost universal quest for easy answers and half-baked solutions. Nothing pains some people more than having to think.",196,"Martin Luther King Jr.",0 198 | "Every man lives in two realms: the internal and the external. The internal is that realm of spiritual ends expressed in art, literature, morals, and religion. The external is that complex of devices, techniques, mechanisms, and instrumentalities by means of which we live.",197,"Martin Luther King Jr.",0 199 | "Shallow understanding from people of good will is more frustrating than absolute misunderstanding from people of ill will.",198,"Martin Luther King Jr.",0 200 | "There comes a time when people get tired of being pushed out of the glittering sunlight of life’s July and left standing amid the piercing chill of an alpine November.",199,"Martin Luther King Jr.",0 201 | "A lie cannot live.",200,"Martin Luther King Jr.",0 202 | "The past is prophetic in that it asserts loudly that wars are poor chisels for carving out peaceful tomorrows.",201,"Martin Luther King Jr.",0 203 | "The limitation of riots, moral questions aside, is that they cannot win and their participants know it. Hence, rioting is not revolutionary but reactionary because it invites defeat. It involves an emotional catharsis, but it must be followed by a sense of futility.",202,"Martin Luther King Jr.",0 204 | "He who is devoid of the power to forgive is devoid of the power to love.",203,"Martin Luther King Jr.",0 205 | "I believe that unarmed truth and unconditional love will have the final word in reality. This is why right, temporarily defeated, is stronger than evil triumphant.",204,"Martin Luther King Jr.",0 206 | "The grass is greener on the other side of the fence.",205,Anonymous,0 207 | "After ~1000 failed coding projects, we've learned one thing: Most coding projects are a waste of time.",206,"QB Devs",0 208 | "When ordering a pizza, a ""Thick Crust"" option means that the *other* options are way too thin.",207,"QB Devs",0 209 | "We're pretty indecisive. Or maybe not. Or maybe we are...",208,"QB Devs",0 210 | "I have 2 questions. 1) How do we solve climate change? 2) Why are there no B batteries?",209,"QB Devs",0 211 | "Knowledge is knowing that a tomato is a fruit; wisdom is not putting it in a fruit salad.",210,"Miles Kington",0 212 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | //"use strict"; 2 | // NPM modules and stuff 3 | const Discord = require("discord.js"); 4 | const { env: envVars } = require("process"); 5 | const fetch = require("node-fetch"); 6 | const cFlags = require("country-flag-emoji"); 7 | const sqlite3 = require("sqlite3"); 8 | const { promisify } = require("util"); 9 | const { version: qbVersion } = require("./package.json"); 10 | const chalk = require("chalk"); 11 | let LeagueAPI = require("leagueapiwrapper"); 12 | const { startCase, escapeRegExp, camelCase, uniqBy } = require('lodash'); 13 | const opggRegions = require("./data/opggRegions.json") 14 | const { Config: SpellCfg, SpellChecker } = require('spech'); 15 | const bot = new Discord.Client(); 16 | require("dotenv").config(); 17 | // config stuff 18 | let configFile; 19 | try { 20 | configFile = require("./config.json"); 21 | } catch (e) { 22 | if (e.code != "MODULE_NOT_FOUND") { 23 | throw e; 24 | } 25 | configFile = { "help-domain": "quotobot.js.org" }; 26 | } 27 | const authorPictures = require("./db/portraits.js"); 28 | const authorWikis = require("./db/wikis.js") 29 | let token; 30 | if (configFile.token == "your-token-here-inside-these-quotes") { 31 | token = envVars.QBTOKEN; 32 | } else if (!configFile.token) { token = envVars.QBTOKEN; } 33 | else { token = configFile.token; } // uses env var if configFile.token isn't there or is the placeholder 34 | // handle starting up the stocks API 35 | let stocksEnabled = false; 36 | if (configFile.stockToken || envVars.QBSTOCKS) { 37 | stocksEnabled = true; 38 | } 39 | if (!stocksEnabled) { 40 | console.log("Your stock API key is falsy (usually undefined). Stock lookups will not work.") 41 | } 42 | const helpDomain = envVars.QBSTATUS || configFile["help-domain"] || undefined; 43 | let helpMessage; 44 | // handle starting up the League API 45 | let leagueEnabled; 46 | try { 47 | if (!envVars.QBRGKEY && !configFile.riotKey) { 48 | throw new Error("The Riot key is falsy (usually undefined). Did you put a key?") 49 | } 50 | else { 51 | // eslint-disable-next-line no-undef 52 | LeagueAPI = new LeagueAPI(envVars.QBRGKEY || configFile.riotKey, Region.NA); 53 | LeagueAPI.getStatus() 54 | .then(() => { 55 | leagueEnabled = true; 56 | console.log("League of Legends lookups are enabled.") 57 | }) 58 | .catch(e => { 59 | leagueEnabled = false; 60 | console.error(chalk`{redBright ${e}}`); 61 | console.error(chalk`{redBright Due to the above error, League of Legends lookups won't work.}`); 62 | }); 63 | } 64 | } 65 | catch (e) { 66 | leagueEnabled = false; 67 | console.error(chalk`{redBright ${e}}`); 68 | console.error(chalk`{redBright Due to the above error, League of Legends lookups won't work.}`); 69 | } 70 | // constants and functions 71 | const prefix = configFile.prefix || envVars.QBPREFIX || "~"; 72 | const norm = text => text 73 | .trim() 74 | .toLowerCase() 75 | .replace(/\s+/, " "); //"normalize" text 76 | const urlPattern = /^(?:http|https):\/\/[^ "]+$/; 77 | const icons = require("./db/icons.js"); 78 | const sp = "📕 Scarlet Pimpernel by Baroness Orczy"; 79 | const randQuoteQuery = "SELECT quote, source FROM Quotes WHERE id IN (SELECT id FROM Quotes ORDER BY RANDOM() LIMIT 1);"; 80 | const usedWeatherRecently = new Set(), usedStocksRecently = new Set(), usedLeagueRecently = new Set(), usedSpellingRecently = new Set(); 81 | const asciiLogo = chalk`{blueBright 82 | ____ __ __ __ 83 | / __ \\__ _____ / /____ / / ___ / /_ 84 | / /_/ / // / _ \\/ __/ _ \\/ _ \\/ _ \\/ __/ 85 | \\___\\_\\_,_/\\___/\\__/\\___/_.__/\\___/\\__/}` // Quotobot in ASCII art 86 | const db = new sqlite3.cached.Database("./db/quotes.db", sqlite3.OPEN_READONLY); 87 | db.each = promisify(db.each); 88 | const embed = Object.freeze({ 89 | "error": (description, code = "", title = "Error") => { 90 | if (!code) { 91 | code = ""; 92 | } else { 93 | code = "`" + code + "`"; 94 | } 95 | return new Discord.MessageEmbed() 96 | .setColor("ff0000") 97 | .setAuthor(title, icons.warn) 98 | .setDescription(`${description} ${code}`); 99 | }, 100 | "simple": (text, attr, title = "Quote") => 101 | new Discord.MessageEmbed() 102 | .setColor(6765239) 103 | .setAuthor("ㅤ", icons.quote) 104 | .setFooter(`—${attr}`, icons.empty) 105 | .setDescription(text) 106 | .setTitle(title), 107 | "stocks": ({ o: open, h: high, l: low, c: current, pc: prevClose, t: timestamp }, 108 | symbol) => new Discord.MessageEmbed() 109 | .setTitle(`Current price for ${symbol.toUpperCase()} is \`${current.toFixed(2)}\``) 110 | .setURL("https://finance.yahoo.com/quote/" + symbol) 111 | .addField("High", "`" + high.toFixed(2) + "`", true) 112 | .addField("Low", "`" + low.toFixed(2) + "`", true) 113 | .addField("Open", "`" + open.toFixed(2) + "`", true) 114 | .addField("Previous Close", "`" + prevClose.toFixed(2) + "`", true) 115 | .setColor(current - prevClose >= 0 ? "4CAF50" : "F44336") 116 | .setFooter("Data from Finnhub") 117 | .setTimestamp(new Date(timestamp * 1000)), 118 | "currWeather": ( // formats the embed for the weather 119 | temp, maxTemp, minTemp, 120 | pressure, humidity, wind, 121 | cloudiness, icon, 122 | author, 123 | cityName, country, units, id, timestamp) => 124 | new Discord.MessageEmbed() 125 | .setColor("ff9800") // yellow 126 | .setAuthor(`Hello, ${author}`) 127 | .setTitle(`It's ${temp}°${units == "metric" ? "C" : "F"} in ${cityName}, ${country}`) 128 | .setURL(`https://openweathermap.org/city/${id}`) 129 | .addField(`🌡 Max Temp`, `${maxTemp}°${units == "metric" ? "C" : "F"}`, true) 130 | .addField(`🌡 Min Temp`, `${minTemp}°${units == "metric" ? "C" : "F"}`, true) 131 | .addField(`💧 Humidity`, `${humidity}%`, true) 132 | .addField(`💨 Wind Speed`, wind, true) 133 | .addField(`📊 Pressure`, `${pressure} hpa`, true) 134 | .addField(`⛅️ Cloudiness`, cloudiness, true) 135 | .setFooter(`This is in ${units} units — you can try ${prefix}weather ${units == "metric" ? "imperial" : "metric"} ${cityName} • Data from OpenWeatherMap`, icons.bulb) 136 | .setThumbnail(`https://openweathermap.org/img/wn/${icon}@2x.png`) 137 | .setTimestamp(new Date(timestamp * 1000)), 138 | }) 139 | bot.once("ready", () => { 140 | console.log(asciiLogo); 141 | db.each(randQuoteQuery).then( 142 | ({ quote, source }) => console.log(chalk`{blueBright "${quote}" –${source}}`) 143 | ) 144 | let invText; 145 | if (configFile.clientID) { 146 | invText = `https://discordapp.com/oauth2/authorize?client_id=${configFile.clientID}&scope=bot&permissions=${configFile.permissionValue.toString() || "280576"}`; 147 | } else { 148 | invText = "Available in the Discord developer portal"; 149 | } 150 | let leagueText; 151 | if (leagueEnabled === false) leagueText = "🚫 League commands will not work" 152 | else if (leagueEnabled) leagueText = "✅"; 153 | else leagueText = "💬 Still trying to start the League API"; 154 | console.table({ 155 | "bot version": qbVersion, prefix, 156 | "username": "@" + bot.user.username + "#" + bot.user.discriminator, 157 | "invite link": invText, 158 | "status": `${prefix}help • ${helpDomain}`, 159 | "server count": bot.guilds.cache.size, 160 | "weather key defined?": (configFile["weather-token"] || envVars.QBWEATHER ? "✅" : "🚫 weather will not work"), 161 | "help link": (configFile.helpURL || "default"), 162 | "stocks enabled?": (stocksEnabled ? "✅" : "🚫 stock commands will not work"), 163 | "league enabled?": leagueText 164 | }) 165 | if (helpDomain) { 166 | bot.user.setActivity(`${prefix}help • ${helpDomain}`, { type: "WATCHING" }); // Custom status "Watching example.qb" 167 | } 168 | helpMessage = `See this link for the commands: ${envVars.QBHELPURL || configFile.helpURL || "https://quotobot.js.org/wiki/Help"} (v${qbVersion}~${bot.guilds.cache.size})`; 169 | }); 170 | if (!token) { 171 | throw new Error("The token is falsy (usually undefined). Make sure you actually put a token in the config file or in the environment variable QBTOKEN."); 172 | } 173 | process.on("SIGTERM", async () => { 174 | try { 175 | if (envVars.QBEXITHOOK) { 176 | const [id, tokn] = envVars.QBEXITHOOK.split("/"); 177 | const hook = new Discord.WebhookClient(id, tokn); 178 | const mbed = new Discord.MessageEmbed() 179 | .setTitle("Shutdown") 180 | .setColor("BLUE") 181 | .setTimestamp(); 182 | await hook.send("Quotobot is shutting down.", { 183 | embeds: [mbed], 184 | }); 185 | } 186 | process.exit(0); 187 | } catch (err) { 188 | console.error(err); 189 | process.exit(1); 190 | } 191 | }) 192 | process.on("uncaughtException", async (err) => { 193 | if (err.name == "DiscordAPIError" && err.message == "Missing Permissions") return; 194 | 195 | console.log(err); 196 | try { 197 | if (envVars.QBEXITHOOK) { 198 | const [id, tokn] = envVars.QBEXITHOOK.split("/"); 199 | const hook = new Discord.WebhookClient(id, tokn); 200 | const mbed = new Discord.MessageEmbed() 201 | .setDescription(err.stack) 202 | .setTitle("Exception") 203 | .setColor("RED") 204 | .setTimestamp(); 205 | await hook.send("Quotobot had an error and is shutting down.", { 206 | embeds: [mbed], 207 | }); 208 | } 209 | } catch (cerr) { 210 | console.error(cerr); 211 | } 212 | process.exit(1); 213 | }) 214 | const splchecker = new SpellChecker(new SpellCfg({ ignoreCase: false, languages: ['en-us'] })); 215 | splchecker.addDictionaryPhrase('Quotobot'); 216 | splchecker.addDictionaryPhrase('quotobot'); 217 | splchecker.addProviderByConfig({ name: 'hunspell' }); 218 | bot.login(token); 219 | bot.on("warn", m => console.warn(chalk`{yellow Warning: ${m}}`)); 220 | bot.on("error", m => console.error(chalk`{redBright Error: ${m}}`)); 221 | bot.on("message", message => { 222 | if (message.author.id == envVars?.QBBAN) return; 223 | const prefixRegex = new RegExp(`^(<@!?${bot.user.id}>|${escapeRegExp(prefix)})\\s*`); 224 | if ((!prefixRegex.test(message.content)) || message.author.bot) return; 225 | const [matchedPrefix] = message.content.match(prefixRegex); 226 | const args = message.content.slice(matchedPrefix.length).trim().split(/ +/); 227 | const command = args.shift().trim().toLowerCase(); 228 | console.count("Command"); 229 | switch (command) { 230 | case "amiadmin": 231 | if (!message.member) return message.reply("Trick question."); 232 | if (!message.member.hasPermission("ADMINISTRATOR")) return message.reply("you're not admin!"); 233 | else return message.reply("you are admin!"); 234 | case "testdm": 235 | message.author.send("Looks like the DM worked! You can send commands in here.") 236 | .catch(error => { 237 | if (error.message == "Cannot send messages to this user") { 238 | message.reply("Oof, you seem to have DMs off."); 239 | } else { console.error(error); } 240 | }); 241 | break; 242 | case "help": 243 | // message.channel.send(new Discord.MessageEmbed() 244 | // .setTitle("⁉️ Click here for the commands.") 245 | // .setColor("009688") 246 | // .setURL(envVars.QBHELPURL || configFile.helpURL || "https://quotobot.js.org/wiki/Help") 247 | // .setFooter(`v${qbVersion}~${bot.guilds.cache.size}`)); 248 | message.channel.send(helpMessage); 249 | break; 250 | case "ping": 251 | message.channel.send("Pong!"); 252 | break; 253 | case "randomquote": 254 | case "randquote": 255 | case "rquote": 256 | case "quote": 257 | { 258 | (async () => { 259 | try { 260 | let { quote, source } = await db.each(randQuoteQuery); 261 | let em = embed.simple(quote, source, "Random Quote"); 262 | if (authorPictures[source.trim()] && urlPattern.test(authorPictures[source.trim()])) { 263 | em.setThumbnail(authorPictures[source.trim()]); 264 | em.setFooter(`—${source}`, authorPictures[source.trim()]); 265 | } 266 | if (source.trim() in authorWikis) { 267 | if (authorWikis[source.trim()] !== null) 268 | em.setAuthor("Click here for author's wiki", icons.quote, "https://en.wikipedia.org/wiki/" + encodeURIComponent(authorWikis[source.trim()])); 269 | } else { 270 | em.setAuthor("Click here for author's wiki", icons.quote, "https://en.wikipedia.org/wiki/" + encodeURIComponent(source.trim())); 271 | } 272 | message.channel.send(em); 273 | } catch (err) { 274 | message.reply(embed.error("There was an error on our end. Try again later.", "ERR_DATABASE")); 275 | console.error(err.message); 276 | } 277 | })(); 278 | // (I've given this quote ${randomQuote.usage} times before) 279 | /* db.run(`Update Quotes set usage = ? where id = ?`, 280 | [randomQuote.usage + 1, randomQuote.id], 281 | (error) => { if (error) { console.log(error.message); } } 282 | ); */ 283 | break; 284 | } 285 | case "shortquot": 286 | case "tweetquote": 287 | case "shortquote": 288 | { 289 | (async () => { 290 | try { 291 | let { quote, source } = await db.each("SELECT quote, source FROM Quotes WHERE id IN (SELECT id FROM Quotes where length(quote) <= 140 ORDER BY RANDOM() LIMIT 1);"); 292 | let em = embed.simple(quote, source, "Random Quote"); 293 | if (authorPictures[source.trim()] && urlPattern.test(authorPictures[source.trim()])) { 294 | em.setThumbnail(authorPictures[source.trim()]); 295 | em.setFooter(`—${source}`, authorPictures[source.trim()]); 296 | } 297 | em.setAuthor("Click here to tweet this quote!", icons.quote, `https://twitter.com/intent/tweet?text=${encodeURIComponent(`As ${source} once said, "${quote}" (from Quotobot <${envVars.QBSTATUS || configFile.helpDomain || "quotobot.js.org"}>)`)}`); 298 | message.channel.send(em); 299 | } catch (err) { 300 | message.reply(embed.error("There was an error on our end. Try again later.", "ERR_DATABASE")); 301 | console.error(err.message); 302 | } 303 | })(); 304 | break; 305 | } 306 | case "longquote": 307 | case "longquot": 308 | { 309 | (async () => { 310 | try { 311 | let { quote, source } = await db.each("SELECT quote, source FROM Quotes WHERE id IN (SELECT id FROM Quotes where length(quote) > 140 ORDER BY RANDOM() LIMIT 1);"); 312 | let em = embed.simple(quote, source, "Random Quote"); 313 | if (authorPictures[source.trim()] && urlPattern.test(authorPictures[source.trim()])) { 314 | em.setThumbnail(authorPictures[source.trim()]); 315 | em.setFooter(`—${source}`, authorPictures[source.trim()]); 316 | } 317 | if (source.trim() in authorWikis) { 318 | if (authorWikis[source.trim()] !== null) 319 | em.setAuthor("Click here for author's wiki", icons.quote, "https://en.wikipedia.org/wiki/" + encodeURIComponent(authorWikis[source.trim()])); 320 | } else { 321 | em.setAuthor("Click here for author's wiki", icons.quote, "https://en.wikipedia.org/wiki/" + encodeURIComponent(source.trim())); 322 | } 323 | message.channel.send(em); 324 | } catch (err) { 325 | message.reply(embed.error("There was an error on our end. Try again later.", "ERR_DATABASE")); 326 | console.error(err.message); 327 | } 328 | })(); 329 | break; 330 | } 331 | case "bibot": 332 | message.channel.send(embed.simple("Morbleu!", sp)); 333 | break; 334 | case "intenselove": 335 | message.channel.send(embed.simple( 336 | "He seemed so devoted — a very slave — and there was a certain latent intensity in that love which had fascinated her.", sp)); 337 | break; 338 | case "contempt": 339 | message.channel.send(embed.simple( 340 | "Thus human beings judge of one another, superficially, casually, throwing contempt on one another, with but little reason, and no charity.", sp)); 341 | break; 342 | case "percysmart": 343 | message.channel.send(embed.simple( 344 | "He was calmly eating his soup, laughing with pleasant good-humour, as if he had come all the way to Calais for the express purpose of enjoying supper at this filthy inn, in the company of his arch-enemy.", sp)); 345 | break; 346 | case "moneynomatter": 347 | message.channel.send(embed.simple( 348 | "Those friends who knew, laughed to scorn the idea that Marguerite St. Just had married a fool for the sake of the worldly advantages with which he might endow her. They knew, as a matter of fact, that Marguerite St. Just cared nothing about money, and still less about a title.", sp)); 349 | break; 350 | case "brains": 351 | message.channel.send(embed.simple( 352 | '"Money and titles may be hereditary," she would say, "but brains are not."', sp)); 353 | break; 354 | case "sppoem": 355 | message.channel.send(embed.simple( 356 | "We seek him here, we seek him there, those Frenchies seek him everywhere. Is he in heaven? — Is he in hell? That demmed, elusive Pimpernel?", sp)); 357 | break; 358 | case "haters": 359 | message.channel.send(embed.simple( 360 | "How that stupid, dull Englishman ever came to be admitted within the intellectual circle which revolved round “the cleverest woman in Europe,” as her friends unanimously called her, no one ventured to guess—a golden key is said to open every door, asserted the more malignantly inclined.", sp)); 361 | break; 362 | case "weathermetric": 363 | case "weather": { 364 | let timeout = configFile.weatherTimeout || envVars.QBWTIMEOUT || 15000 365 | if (usedWeatherRecently.has(message.author.id)) { 366 | message.reply(embed.error(`You need to wait ${timeout / 1000} seconds before asking for the weather again.`, "ERR_RATE_LIMIT", "Slow down!")); 367 | } else { 368 | (async () => { 369 | if (!(configFile["weather-token"] || envVars.QBWEATHER)) { 370 | message.reply(embed.error("Weather isn't currently working. Sorry about that.", "ERR_FALSY_WEATHER_KEY")); 371 | console.error("Error: The weather key is falsy (usually undefined). Make sure you actually put a key in the config.json or in env.QBWEATHER.") 372 | return; 373 | } 374 | if (!args[0]) { 375 | message.reply(embed.error("You didn't include any arguments. Re-run the command with *metric* or *imperial* and the city name.")); 376 | return null; 377 | } 378 | let units = ["metric", "imperial"].includes(norm(args[0])) ? norm(args[0]) : "metric"; 379 | let city = !(["metric", "imperial"].includes(norm(args[0]))) ? args.slice(0).join(" ") : args.slice(1).join(" "); 380 | if (!city) { 381 | message.reply(embed.error("You didn't include a city name. Re-run the command with the city name.", `args: ${args.toString()}`)); 382 | return null; 383 | } 384 | let windUnits = units == "imperial" ? "mph" : "m/s"; 385 | 386 | try { 387 | let apiData = await fetch( 388 | `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units}&APPID=${configFile["weather-token"] || envVars.QBWEATHER}` 389 | ); 390 | let jd = await apiData.json(); 391 | if (!apiData.ok) { 392 | message.reply(embed.error("There was an error getting the weather.", `${jd.cod || apiData.status}: ${jd.message || apiData.statusText}`)); 393 | return; 394 | } 395 | let { temp, temp_max, temp_min, humidity, pressure } = jd.main; 396 | let currentTemp = Math.round(temp); 397 | let maxTemp = Math.round(temp_max); 398 | let minTemp = Math.round(temp_min); 399 | let wind = jd.wind.speed + " " + windUnits; 400 | let { username } = message.author; 401 | let { icon, description: cloudness } = jd.weather[0]; 402 | let { id, name: displayCity, dt: timestamp } = jd; 403 | let { country } = jd.sys; 404 | country += cFlags.get(country).emoji ? " " + cFlags.get(country).emoji : ""; 405 | message.reply(embed.currWeather(currentTemp, maxTemp, minTemp, pressure, humidity, wind, cloudness, icon, username, displayCity, country, units, id, timestamp)); 406 | // Adds the user to the set so that they can't get weather for some time 407 | usedWeatherRecently.add(message.author.id); 408 | setTimeout(() => { 409 | // Removes the user from the set after timeout 410 | usedWeatherRecently.delete(message.author.id); 411 | }, timeout); 412 | } catch (err) { 413 | message.reply(embed.error("There was an error getting the weather.", `${err.toString().replaceAll(configFile["weather-token"] || envVars.QBWEATHER, "")}`)); 414 | } finally { 415 | if (city == "constantinople") message.reply("https://youtube.com/watch?v=vsQrKZcYtqg"); 416 | } 417 | })(); 418 | } 419 | break; 420 | } 421 | case "gotanygrapes": 422 | message.reply("https://www.youtube.com/watch?v=MtN1YnoL46Q"); // duck song 423 | break; 424 | case "stocks": 425 | case "stock": { 426 | const timeout = configFile.stockTimeout || envVars.QBSTIMEOUT || configFile.weatherTimeout || envVars.QBWTIMEOUT || 2000; 427 | if (usedStocksRecently.has(message.author.id)) { 428 | message.reply(embed.error(`You need to wait ${timeout / 1000} seconds before asking for stocks again.`, "ERR_RATE_LIMIT", "Slow down!")); 429 | } else { 430 | (async () => { 431 | if (!stocksEnabled) { 432 | message.reply(embed.error("Stock lookup isn't currently working. Sorry about that.", "ERR_NO_STOCK_KEY")); 433 | return null; 434 | } 435 | if (!args[0]) { 436 | message.reply(embed.error("You didn't include any arguments. Re-run the command with the stock name.")); 437 | return null; 438 | } 439 | try { 440 | let gotData = await fetch(`https://finnhub.io/api/v1/quote?symbol=${args[0].toUpperCase()}&token=${configFile.stockToken || envVars.QBSTOCKS}`); 441 | let stockData = await gotData.json(); 442 | if (!gotData.ok) { 443 | message.reply(embed.error("There was an error getting stock info.", `${stockData.cod || gotData.status}: ${stockData.message || gotData.statusText}`)); 444 | return; 445 | } 446 | if (!stockData) { 447 | message.reply(embed.error(`${args[0]} was not found.`, "ERR_EMPTY_RESPONSE")); 448 | return null; 449 | } else if (stockData.error || 450 | (Object.keys(stockData).length == 0 && stockData.constructor === Object) || 451 | Object.values(stockData).includes(undefined) || 452 | stockData.t === 0) { 453 | message.reply(embed.error(`${args[0]} was not found.`, (stockData.error || "ERR_ALLSTOCK_ZERO"))); 454 | return null; 455 | } 456 | message.reply(embed.stocks(stockData, args[0])); 457 | } catch (err) { 458 | message.reply(embed.error("There was an error getting stock info.", (err.toString() || "ERR_FETCH").replace(configFile.stockToken || envVars.QBSTOCKS, ""))) 459 | } 460 | })(); 461 | usedStocksRecently.add(message.author.id); 462 | setTimeout(() => { 463 | // Removes the user from the set after timeout 464 | usedStocksRecently.delete(message.author.id); 465 | }, timeout); 466 | } 467 | break; 468 | } 469 | case "league": 470 | case "lolstats": 471 | case "lol": 472 | case "leaguestats": { 473 | const timeout = configFile.leagueTimeout || envVars.QBLEAGUETIMEOUT || 5000; 474 | if (usedLeagueRecently.has(message.author.id)) { 475 | message.reply(embed.error(`You need to wait ${timeout / 1000} seconds before asking for League stats again.`, "ERR_RATE_LIMIT", "Slow down!")); 476 | return; 477 | } 478 | if (!leagueEnabled) { 479 | message.reply(embed.error("League stats lookup isn't currently working. Sorry about that.", "ERR_NO_LEAGUE_KEY")); 480 | return; 481 | } 482 | if (!args[0]) { 483 | message.reply(embed.error("You didn't include any arguments. Re-run the command with the summoner name.")); 484 | return; 485 | } 486 | (async () => { 487 | let reg = "NA"; 488 | 489 | if (args[1]) { 490 | reg = args[1].toUpperCase(); 491 | } 492 | try { 493 | message.channel.startTyping(); 494 | if (reg != "NA") { 495 | // eslint-disable-next-line no-undef 496 | LeagueAPI.changeRegion(Region[reg]); 497 | } 498 | let acctObj = await LeagueAPI.getSummonerByName(args[0].replace(/\+/g, " ")); 499 | let profile = acctObj?.profileIconId || ""; 500 | if (profile) profile = `https://ddragon.leagueoflegends.com/cdn/${LeagueAPI.getDDragonLocalDataVersion()}/img/profileicon/${profile}.png`; 501 | let addlData = await LeagueAPI.getLeagueRanking(acctObj) || []; 502 | message.channel.stopTyping(true); 503 | let mbed = embed.simple( 504 | "", "", `League Info for ${acctObj.name}`) 505 | .setURL(`https://${opggRegions[LeagueAPI.region]}.op.gg/summoner/userName=${acctObj.name.replace(/ /g, "+")}`) 506 | .setFooter('Click the "League Info" title above to go to this summoner\'s OP.GG page.', icons.bulb) 507 | .setThumbnail(profile) 508 | .addField("Summoner Level", acctObj.summonerLevel, false); 509 | const exclKeys = ["summonerName", "wins", "losses"]; 510 | addlData.forEach((_ranked, idx) => { // Iterate over each ranked data set 511 | const fields = addlData[idx]; 512 | Object.keys(fields).forEach((key) => { // iterate over each field 513 | if (key == "queueType") mbed.addField(startCase(key), startCase(camelCase(String(fields[key]))), true) 514 | else if (!key.endsWith("Id") && !exclKeys.includes(key)) { 515 | let val = fields[key]; 516 | if (typeof val == "boolean") val = val ? "✅ Yes" : "🚫 No"; 517 | mbed.addField(startCase(key), String(val), true) 518 | } 519 | }); 520 | if (fields.wins && fields.losses) { 521 | const total = fields.wins + fields.losses; 522 | const rate = Math.round((fields.wins / total) * 100); 523 | mbed.addField("Win Rate", `**${rate}%** (${total}G ${fields.wins}W ${fields.losses}L)`) 524 | } 525 | if (idx + 1 != addlData.length) mbed.addField('\u200b', '\u200b'); // Blank field 526 | }); 527 | message.reply(mbed); 528 | // eslint-disable-next-line no-undef 529 | LeagueAPI.changeRegion(Region.NA); 530 | } catch (err) { 531 | let errmessage = err?.status?.message || err?.message || err; 532 | if (errmessage == 533 | "Error: getaddrinfo ENOTFOUND undefined.api.riotgames.com" 534 | ) errmessage = "Invalid Region"; 535 | message.reply(embed.error("There was an error getting League stats.", errmessage)); 536 | message.channel.stopTyping(true); 537 | message.channel.stopTyping(); 538 | // eslint-disable-next-line no-undef 539 | LeagueAPI.changeRegion(Region.NA); 540 | return null; 541 | } 542 | })(); 543 | usedLeagueRecently.add(message.author.id); 544 | setTimeout(() => { 545 | // Removes the user from the set after timeout 546 | usedLeagueRecently.delete(message.author.id); 547 | }, timeout); 548 | } 549 | break; 550 | case "spellcheck": 551 | if (envVars.QBSPELL != "off") { 552 | (async () => { 553 | let timeout = envVars.QBSPTIMEOUT || 10000; 554 | if (usedSpellingRecently.has(message.author.id)) return message.reply(embed.error(`You need to wait ${timeout / 1000} seconds before asking for spellcheck again.`, "ERR_RATE_LIMIT", "Slow down!")); 555 | if (args?.length < 1) return message.reply(embed.error("You didn't include any text to spell check.", "ERR_NO_TEXT", "Where's the text?")); 556 | if (args?.join().length > 500) return message.reply(embed.error("You can only spellcheck 500 characters at most.", "ERR_500_EXCEEDED", "Too long!")); 557 | 558 | usedSpellingRecently.add(message.author.id); 559 | setTimeout(() => { 560 | usedSpellingRecently.delete(message.author.id); 561 | }, timeout); 562 | let { items } = await splchecker.checkText(args.join(" ")); 563 | if (!items || items.length < 1) return message.reply(new Discord.MessageEmbed().setTitle("No errors found.").setColor(6765239)); 564 | items = uniqBy(items, "fragment"); 565 | let desc = ""; 566 | const mbed = new Discord.MessageEmbed() 567 | .setColor(6765239) 568 | .setTitle("Spell Check"); 569 | items.some(({ fragment, suggestions }) => { 570 | let addition = `~~${fragment}~~ → **${suggestions.join("**, **") || "No suggestions"} **\n`; 571 | if (desc.length + addition.length > 2000) { 572 | mbed.setFooter("This spellcheck has been shortened."); 573 | return true; 574 | } 575 | else desc += addition; 576 | }); 577 | mbed.setDescription(desc); 578 | return message.reply(mbed); 579 | })() 580 | } 581 | break; 582 | case "github": 583 | message.channel.send("https://github.com/Team-Gigabyte/quotobot") 584 | break; 585 | default: 586 | break; 587 | } 588 | }); 589 | -------------------------------------------------------------------------------- /db/quotes.db.sql: -------------------------------------------------------------------------------- 1 | PRAGMA foreign_keys=OFF; 2 | BEGIN TRANSACTION; 3 | CREATE TABLE Quotes(quote text not null, id int not null primary key, source text not null, usage int not null); 4 | INSERT INTO Quotes VALUES('Never put off till to-morrow what you can do to-day.',1,'Thomas Jefferson',0); 5 | INSERT INTO Quotes VALUES('Never trouble another for what you can do yourself. ',2,'Thomas Jefferson',0); 6 | INSERT INTO Quotes VALUES('Never spend your money before you have it.',3,'Thomas Jefferson',0); 7 | INSERT INTO Quotes VALUES('Never buy what you do not want, because it is cheap; it will be dear to you.',4,'Thomas Jefferson',0); 8 | INSERT INTO Quotes VALUES('Pride costs us more than hunger, thirst, and cold.',5,'Thomas Jefferson',0); 9 | INSERT INTO Quotes VALUES('We never repent of having eaten too little.',6,'Thomas Jefferson',0); 10 | INSERT INTO Quotes VALUES('Nothing is troublesome that we do willingly.',7,'Thomas Jefferson',0); 11 | INSERT INTO Quotes VALUES('How much pain have cost us the evils which have never happened.',8,'Thomas Jefferson',0); 12 | INSERT INTO Quotes VALUES('Take things always by their smooth handle.',9,'Thomas Jefferson',0); 13 | INSERT INTO Quotes VALUES('When angry, count ten, before you speak; if very angry, a hundred.',10,'Thomas Jefferson',0); 14 | INSERT INTO Quotes VALUES('It is better to offer no excuse than a bad one. ',11,'George Washington',0); 15 | INSERT INTO Quotes VALUES('It is better to be alone than in bad company. ',12,'George Washington',0); 16 | INSERT INTO Quotes VALUES('If freedom of speech is taken away, then dumb and silent we may be led, like sheep to the slaughter.',13,'George Washington',0); 17 | INSERT INTO Quotes VALUES('But lest some unlucky event should happen unfavorable to my reputation, I beg it may be remembered by every gentleman in the room that I this day declare with the utmost sincerity, I do not think myself equal to the command I am honored with.',14,'George Washington',0); 18 | INSERT INTO Quotes VALUES('A primary object should be the education of our youth in the science of government. In a republic, what species of knowledge can be equally important? And what duty more pressing than communicating it to those who are to be the future guardians of the liberties of the country?',15,'George Washington',0); 19 | INSERT INTO Quotes VALUES('Be courteous to all, but intimate with few, and let those few be well tried before you give them your confidence. True friendship is a plant of slow growth, and must undergo and withstand the shocks of adversity before it is entitled to appellation.',16,'George Washington',1); 20 | INSERT INTO Quotes VALUES('A free people ought not only to be armed, but disciplined; to which end a uniform and well-digested plan is requisite; and their safety and interest require that they should promote such manufactories as tend to render them independent of others for essential, particularly military, supplies.',17,'George Washington',0); 21 | INSERT INTO Quotes VALUES('Human happiness and moral duty are inseparably connected.',18,'George Washington',0); 22 | INSERT INTO Quotes VALUES('However [political parties] may now and then answer popular ends, they are likely in the course of time and things, to become potent engines, by which cunning, ambitious, and unprincipled men will be enabled to subvert the power of the people and to usurp for themselves the reins of government, destroying afterwards the very engines which have lifted them to unjust dominion.',19,'George Washington',0); 23 | INSERT INTO Quotes VALUES('99% of failures come from people who make excuses.',20,'George Washington',0); 24 | INSERT INTO Quotes VALUES('Guard against the impostures of pretended patriotism.',21,'George Washington',0); 25 | INSERT INTO Quotes VALUES('Labor to keep alive in your breast that little spark of celestial fire called conscience.',22,'George Washington',0); 26 | INSERT INTO Quotes VALUES('Perseverance and spirit have done wonders in all ages.',23,'George Washington',0); 27 | INSERT INTO Quotes VALUES('Associate yourself with men of good quality, if you esteem your own reputation; for ‘tis better to be alone than in bad company.',24,'George Washington',0); 28 | INSERT INTO Quotes VALUES('Few men have virtue to withstand the highest bidder.',25,'George Washington',0); 29 | INSERT INTO Quotes VALUES('Happiness depends more upon the internal frame of a person’s own mind, than on the externals in the world.',26,'George Washington',0); 30 | INSERT INTO Quotes VALUES('Experience teaches us that it is much easier to prevent an enemy from posting themselves than it is to dislodge them after they have got possession. ',27,'George Washington',0); 31 | INSERT INTO Quotes VALUES('The harder the conflict, the greater the triumph',28,'George Washington',0); 32 | INSERT INTO Quotes VALUES('Worry is the interest paid by those who borrow trouble.',29,'George Washington',0); 33 | INSERT INTO Quotes VALUES('The turning points of lives are not the great moments. The real crises are often concealed in occurrences so trivial in appearance that they pass unobserved.',30,'George Washington',0); 34 | INSERT INTO Quotes VALUES('Real men despise battle, but will never run from it.',31,'George Washington',0); 35 | INSERT INTO Quotes VALUES('Discipline is the soul of an army. It makes small numbers formidable; procures success to the weak, and esteem to all.',32,'George Washington',0); 36 | INSERT INTO Quotes VALUES('Citizens by birth or choice of a common country, that country has a right to concentrate your affections. The name of American, which belongs to you, in your national capacity, must always exalt the just pride of Patriotism, more than any appellation derived from local discriminations.',33,'George Washington',0); 37 | INSERT INTO Quotes VALUES('We should not look back unless it is to derive useful lessons from past errors, and for the purpose of profiting by dearly bought experience.',34,'George Washington',0); 38 | INSERT INTO Quotes VALUES('I read my eyes out and can''t read half enough...the more one reads the more one sees we have to read.',35,'John Adams',0); 39 | INSERT INTO Quotes VALUES('Let us tenderly and kindly cherish therefore, the means of knowledge. Let us dare to read, think, speak, and write.',36,'John Adams',0); 40 | INSERT INTO Quotes VALUES('Facts are stubborn things; and whatever may be our wishes, our inclinations, or the dictates of our passion, they cannot alter the state of facts and evidence.',37,'John Adams',0); 41 | INSERT INTO Quotes VALUES('A Constitution of Government once changed from Freedom, can never be restored. Liberty, once lost, is lost forever.',38,'John Adams',0); 42 | INSERT INTO Quotes VALUES('The longer I live, the more I read, the more patiently I think, and the more anxiously I inquire, the less I seem to know...Do justly. Love mercy. Walk humbly. This is enough.',39,'John Adams',0); 43 | INSERT INTO Quotes VALUES('There is nothing which I dread so much as a division of the republic into two great parties, each arranged under its leader, and concerting measures in opposition to each other. This, in my humble apprehension, is to be dreaded as the greatest political evil under our Constitution.',40,'John Adams',0); 44 | INSERT INTO Quotes VALUES('Posterity! you will never know how much it cost the present generation to preserve your freedom! I hope you will make a good use of it.',41,'John Adams',0); 45 | INSERT INTO Quotes VALUES('I say, that Power must never be trusted without a check.',42,'John Adams',0); 46 | INSERT INTO Quotes VALUES('Children should be educated and instructed in the principles of freedom. Aristotle speaks plainly to this purpose, saying, ''that the institution of youth should be accommodated to that form of government under which they live; forasmuch as it makes exceedingly for the preservation of the present government, whatsoever it be.',43,'John Adams',0); 47 | INSERT INTO Quotes VALUES('Let the human mind loose. It must be loose. It will be loose. Superstition and dogmatism cannot confine it.',44,'John Adams',0); 48 | INSERT INTO Quotes VALUES('I must judge for myself, but how can I judge, how can any man judge, unless his mind has been opened and enlarged by reading.',45,'John Adams',0); 49 | INSERT INTO Quotes VALUES('To believe all men honest is folly. To believe none is something worse.',46,'John Adams',1); 50 | INSERT INTO Quotes VALUES('Government has no right to hurt a hair on the head of an Atheist for his Opinions. Let him have a care of his Practices.',47,'John Adams',0); 51 | INSERT INTO Quotes VALUES('You will never be alone with a poet in your pocket.',48,'John Adams',0); 52 | INSERT INTO Quotes VALUES('The way to secure liberty is to place it in the people''s hands, that is, to give them the power at all times to defend it in the legislature and in the courts of justice.',49,'John Adams',0); 53 | INSERT INTO Quotes VALUES('There is danger from all men. The only maxim of a free government ought to be to trust no man living with power to endanger the public liberty.',50,'John Adams',0); 54 | INSERT INTO Quotes VALUES('The happiness of society is the end of government.',51,'John Adams',0); 55 | INSERT INTO Quotes VALUES('Be not intimidated...nor suffer yourselves to be wheedled out of your liberties by any pretense of politeness, delicacy, or decency. These, as they are often used, are but three different names for hypocrisy, chicanery and cowardice.',52,'John Adams',0); 56 | INSERT INTO Quotes VALUES('And liberty cannot be preserved without a general knowledge among the people who have a right from the frame of their nature to knowledge...',53,'John Adams',0); 57 | INSERT INTO Quotes VALUES('Without the pen of Paine, the sword of Washington would have been wielded in vain.',54,'John Adams',0); 58 | INSERT INTO Quotes VALUES('Laws for the liberal education of youth, especially of the lower class of people, are so extremely wise and useful, that, to a humane and generous mind, no expense for this purpose would be thought extravagant.',55,'John Adams',0); 59 | INSERT INTO Quotes VALUES('Old minds are like old horses; you must exercise them if you wish to keep them in working order.',56,'John Adams',0); 60 | INSERT INTO Quotes VALUES('Nineteen twentieths of [mankind is] opaque and unenlightened. Intimacy with most people will make you acquainted with vices and errors and follies enough to make you despise them.',57,'John Adams',0); 61 | INSERT INTO Quotes VALUES('If worthless men are sometimes at the head of affairs, it is, I believe, because worthless men are at the tail and the middle',58,'John Adams',1); 62 | INSERT INTO Quotes VALUES('When legislature is corrupted, the people are undone.',59,'John Adams',0); 63 | INSERT INTO Quotes VALUES('The true source of our sufferings has been our timidity.',60,'John Adams',0); 64 | INSERT INTO Quotes VALUES('Everything in life should be done with reflection.',61,'John Adams',0); 65 | INSERT INTO Quotes VALUES('Great is the guilt of an unnecessary war.',62,'John Adams',0); 66 | INSERT INTO Quotes VALUES('The jaws of power are always open to devour, and her arm is always stretched out, if possible, to destroy the freedom of thinking, speaking, and writing.',63,'John Adams',0); 67 | INSERT INTO Quotes VALUES('Abuse of words has been the great instrument of sophistry and chicanery, of party, faction, and division of society.',64,'John Adams',0); 68 | INSERT INTO Quotes VALUES('Property monopolized or in the possession of a few is a curse to mankind.',65,'John Adams',0); 69 | INSERT INTO Quotes VALUES('Work smarter, not harder — something we should''ve followed more when making this.',66,'QB Devs',0); 70 | INSERT INTO Quotes VALUES('Always make sure you know what work the other people in a group project will do before starting work on the project.',67,'QB Devs',0); 71 | INSERT INTO Quotes VALUES('He seemed so devoted — a very slave — and there was a certain latent intensity in that love which had fascinated her.',68,'*The Scarlet Pimpernel* by Baroness Orczy',0); 72 | INSERT INTO Quotes VALUES('Thus human beings judge of one another, superficially, casually, throwing contempt on one another, with but little reason, and no charity.',69,'*The Scarlet Pimpernel* by Baroness Orczy',0); 73 | INSERT INTO Quotes VALUES('He was calmly eating his soup, laughing with pleasant good-humour, as if he had come all the way to Calais for the express purpose of enjoying supper at this filthy inn, in the company of his arch-enemy.',70,'*The Scarlet Pimpernel* by Baroness Orczy',0); 74 | INSERT INTO Quotes VALUES('Those friends who knew, laughed to scorn the idea that Marguerite St. Just had married a fool for the sake of the worldly advantages with which he might endow her. They knew, as a matter of fact, that Marguerite St. Just cared nothing about money, and still less about a title.',71,'*The Scarlet Pimpernel* by Baroness Orczy',0); 75 | INSERT INTO Quotes VALUES('"Money and titles may be hereditary," she would say, "but brains are not."',72,'*The Scarlet Pimpernel* by Baroness Orczy',0); 76 | INSERT INTO Quotes VALUES('We seek him here, we seek him there, Those Frenchies seek him everywhere. Is he in heaven? — Is he in hell? That demmed, elusive Pimpernel?',73,'*The Scarlet Pimpernel* by Baroness Orczy',0); 77 | INSERT INTO Quotes VALUES('How that stupid, dull Englishman ever came to be admitted within the intellectual circle which revolved round “the cleverest woman in Europe,” as her friends unanimously called her, no one ventured to guess—a golden key is said to open every door, asserted the more malignantly inclined.',74,'*The Scarlet Pimpernel* by Baroness Orczy',0); 78 | INSERT INTO Quotes VALUES('This is an example.',75,'QB Devs',0); 79 | INSERT INTO Quotes VALUES('Ask not what your country can do for you; ask what you can do for your country.',76,'John F. Kennedy',0); 80 | INSERT INTO Quotes VALUES('If not us, who? If not now, when?',77,'John F. Kennedy',0); 81 | INSERT INTO Quotes VALUES('Every accomplishment starts with the decision to try.',78,'John F. Kennedy',0); 82 | INSERT INTO Quotes VALUES('As we express our gratitude, we must never forget that the highest form of appreciation is not to utter words, but to live by them.',79,'John F. Kennedy',0); 83 | INSERT INTO Quotes VALUES('Those who dare to fail miserably can achieve greatly.',80,'John F. Kennedy',0); 84 | INSERT INTO Quotes VALUES('The ignorance of one voter in a democracy impairs the security of all.',81,'John F. Kennedy',0); 85 | INSERT INTO Quotes VALUES('Do not pray for easy lives, pray to be stronger men.',82,'John F. Kennedy',0); 86 | INSERT INTO Quotes VALUES('Leadership and learning are indispensable to each other.',83,'John F. Kennedy',0); 87 | INSERT INTO Quotes VALUES('Life is never easy. There is work to be done and obligations to be met—obligations to truth, to justice, and to liberty.',84,'John F. Kennedy',0); 88 | INSERT INTO Quotes VALUES('Too often we enjoy the comfort of opinion without the discomfort of thought.',85,'John F. Kennedy',0); 89 | INSERT INTO Quotes VALUES('We have the power to make this the best generation of mankind in the history of the world or make it the last.',86,'John F. Kennedy',0); 90 | INSERT INTO Quotes VALUES('The greater our knowledge increases the more our ignorance unfolds.',87,'John F. Kennedy',0); 91 | INSERT INTO Quotes VALUES('There''s not a liberal America and a conservative America — there''s the United States of America.',88,'Barack Obama',0); 92 | INSERT INTO Quotes VALUES('Change will not come if we wait for some other person or if we wait for some other time. We are the ones we''ve been waiting for. We are the change that we seek.',89,'Barack Obama',0); 93 | INSERT INTO Quotes VALUES('Where we are met with cynicism and doubts and those who tell us that we can''t, we will respond with that timeless creed that sums up the spirit of a people: Yes, we can.',90,'Barack Obama',0); 94 | INSERT INTO Quotes VALUES('Clear-eyed, we can understand that there will be war, and still strive for peace.',91,'Barack Obama',0); 95 | INSERT INTO Quotes VALUES('With eyes fixed on the horizon and God''s grace upon us, we carried forth that great gift of freedom and delivered it safely to future generations.',92,'Barack Obama',0); 96 | INSERT INTO Quotes VALUES('There has been one constant amidst these shifting tides. At every turn, America''s men and women in uniform have served with courage and resolve.',93,'Barack Obama',0); 97 | INSERT INTO Quotes VALUES('We should do everything we can to make sure this country lives up to our children''s expectations.',94,'Barack Obama',0); 98 | INSERT INTO Quotes VALUES('As it has for more than two centuries, progress will come in fits and starts. It''s not always a straight line. It''s not always a smooth path.',95,'Barack Obama',0); 99 | INSERT INTO Quotes VALUES('The strongest weapon against hateful speech is not repression; it is more speech.',96,'Barack Obama',0); 100 | INSERT INTO Quotes VALUES('The cynics may be the loudest voices, — but I promise you, they will accomplish the least.',97,'Barack Obama',0); 101 | INSERT INTO Quotes VALUES('We choose hope over fear. We see the future not as something out of our control, but as something we can shape for the better through concerted and collective effort.',98,'Barack Obama',0); 102 | INSERT INTO Quotes VALUES('To be an American is about something more than what we look like, or what our last names are, or how we worship.',99,'Barack Obama',0); 103 | INSERT INTO Quotes VALUES('It is you, the young and fearless at heart, the most diverse and educated generation in our history, who the nation is waiting to follow.',100,'Barack Obama',0); 104 | INSERT INTO Quotes VALUES('No matter who you are or what you look like, how you started off, or how and who you love, America is a place where you can write your own destiny.',101,'Barack Obama',0); 105 | INSERT INTO Quotes VALUES('That''s the America I know. That''s the country we love. Clear-eyed. Big-hearted. Undaunted by challenge.',102,'Barack Obama',0); 106 | INSERT INTO Quotes VALUES('The long sweep of America has been defined by forward motion, a constant widening of our founding creed to embrace all and not just some.',103,'Barack Obama',0); 107 | INSERT INTO Quotes VALUES('To quote or not to quote, that is the question.',104,'QB Devs',0); 108 | INSERT INTO Quotes VALUES('Men give me credit for some genius. All the genius I have lies in this; when I have a subject in hand, I study it profoundly. Day and night it is before me. My mind becomes pervaded with it. Then the effort that I have made is what people are pleased to call the fruit of genius. It is the fruit of labor and thought.',106,'Alexander Hamilton',0); 109 | INSERT INTO Quotes VALUES('Those who stand for nothing fall for everything.',107,'Alexander Hamilton',0); 110 | INSERT INTO Quotes VALUES('Give all the power to the many, they will oppress the few. Give all the power to the few, they will oppress the many.',108,'Alexander Hamilton',0); 111 | INSERT INTO Quotes VALUES('The constitution shall never be construed...to prevent the people of the United States who are peaceable citizens from keeping their own arms.',109,'Alexander Hamilton',0); 112 | INSERT INTO Quotes VALUES('A well adjusted person is one who makes the same mistake twice without getting nervous.',110,'Alexander Hamilton',0); 113 | INSERT INTO Quotes VALUES('The art of reading is to skip judiciously.',111,'Alexander Hamilton',0); 114 | INSERT INTO Quotes VALUES('I never expect a perfect work from an imperfect man.',112,'Alexander Hamilton',0); 115 | INSERT INTO Quotes VALUES('A nation which can prefer disgrace to danger is prepared for a master, and deserves one.',113,'Alexander Hamilton',0); 116 | INSERT INTO Quotes VALUES('There are seasons in every country when noise and impudence pass current for worth; and in popular commotions especially, the clamors of interested and factious men are often mistaken for patriotism.',114,'Alexander Hamilton',0); 117 | INSERT INTO Quotes VALUES('The sacred rights of mankind are not to be rummaged for among old parchments or musty records. They are written, as with a sunbeam, in the whole volume of human nature, by the Hand of Divinity itself, and can never be erased or obscured by mortal power.',115,'Alexander Hamilton',0); 118 | INSERT INTO Quotes VALUES('Hard words are very rarely useful. Real firmness is good for every thing. Strut is good for nothing.',116,'Alexander Hamilton',0); 119 | INSERT INTO Quotes VALUES('I have thought it my duty to exhibit things as they are, not as they ought to be.',117,'Alexander Hamilton',0); 120 | INSERT INTO Quotes VALUES('Men are reasoning rather than reasonable animals.',118,'Alexander Hamilton',0); 121 | INSERT INTO Quotes VALUES('Who talks most about freedom and equality? Is it not those who hold the bill of rights in one hand and a whip for affrighted slaves in the other?',119,'Alexander Hamilton',0); 122 | INSERT INTO Quotes VALUES('The best we can hope for concerning the people at large is that they be properly armed.',120,'Alexander Hamilton',0); 123 | INSERT INTO Quotes VALUES('A powerful, victorious ally is yet another name for master.',121,'Alexander Hamilton',0); 124 | INSERT INTO Quotes VALUES('For in politics, as in religion, it is equally absurd to aim at making proselytes by fire and sword. Heresies in either can rarely be cured by persecution.',122,'Alexander Hamilton',0); 125 | INSERT INTO Quotes VALUES('If we must have an enemy at the head of government, let it be one whom we can oppose, and for whom we are not responsible.',123,'Alexander Hamilton',0); 126 | INSERT INTO Quotes VALUES('Vigor of government is essential to the security of liberty.',124,'Alexander Hamilton',0); 127 | INSERT INTO Quotes VALUES('It will be of little avail to the people, that the laws are made by men of their own choice, if the laws be so voluminous that they cannot be read, or so incoherent that they cannot be understood',125,'Alexander Hamilton',0); 128 | INSERT INTO Quotes VALUES('The inquiry constantly is what will please, not what will benefit the people. In such a government there can be nothing but temporary expedient, fickleness, and folly.',126,'Alexander Hamilton',0); 129 | INSERT INTO Quotes VALUES('The mark of a pro coder is `Build Passing`',127,'QB Devs',0); 130 | INSERT INTO Quotes VALUES('If a teacher gives you several days for an assignment, there is a reason for that; there is a lot of work.',128,'QB Devs',0); 131 | INSERT INTO Quotes VALUES('You can’t let your failures define you. You have to let your failures teach you.',105,'Barack Obama',0); 132 | INSERT INTO Quotes VALUES('Folks are usually about as happy as they make their minds up to be.',129,'Abraham Lincoln',0); 133 | INSERT INTO Quotes VALUES('Whatever you are, be a good one.',130,'Abraham Lincoln',0); 134 | INSERT INTO Quotes VALUES('Do I not destroy my enemies when I make them my friends?',131,'Abraham Lincoln',0); 135 | INSERT INTO Quotes VALUES('America will never be destroyed from the outside. If we falter and lose our freedoms, it will be because we destroyed ourselves.',132,'Abraham Lincoln',0); 136 | INSERT INTO Quotes VALUES('My Best Friend is a person who will give me a book I have not read.',133,'Abraham Lincoln',0); 137 | INSERT INTO Quotes VALUES('Nearly all men can stand adversity, but if you want to test a man''s character, give him power.',134,'Abraham Lincoln',0); 138 | INSERT INTO Quotes VALUES('I''m a success today because I had a friend who believed in me and I didn''t have the heart to let him down.',135,'Abraham Lincoln',0); 139 | INSERT INTO Quotes VALUES('Books serve to show a man that those original thoughts of his aren''t very new after all.',136,'Abraham Lincoln',0); 140 | INSERT INTO Quotes VALUES('Those who deny freedom to others, deserve it not for themselves.',137,'Abraham Lincoln',0); 141 | INSERT INTO Quotes VALUES('Whenever I hear anyone arguing for slavery, I feel a strong impulse to see it tried on him personally.',138,'Abraham Lincoln',0); 142 | INSERT INTO Quotes VALUES('Those who look for the bad in people will surely find it.',139,'Abraham Lincoln',0); 143 | INSERT INTO Quotes VALUES('I am not bound to win, but I am bound to be true. I am not bound to succeed, but I am bound to live up to what light I have.',140,'Abraham Lincoln',0); 144 | INSERT INTO Quotes VALUES('Be sure you put your feet in the right place, then stand firm.',141,'Abraham Lincoln',0); 145 | INSERT INTO Quotes VALUES('You can fool some of the people all of the time, and all of the people some of the time, but you can not fool all of the people all of the time.',142,'Abraham Lincoln',0); 146 | INSERT INTO Quotes VALUES('I would rather be a little nobody than to be [an] evil somebody.',143,'Abraham Lincoln',0); 147 | INSERT INTO Quotes VALUES('Character is like a tree and reputation its shadow. The shadow is what we think it is and the tree is the real thing.',144,'Abraham Lincoln',0); 148 | INSERT INTO Quotes VALUES('Always bear in mind that your own resolution to succeed is more important than any one thing.',145,'Abraham Lincoln',0); 149 | INSERT INTO Quotes VALUES('The best way to predict your future is to create it.',146,'Abraham Lincoln',0); 150 | INSERT INTO Quotes VALUES('Elections belong to the people. It''s their decision. If they decide to turn their back on the fire and burn their behinds, then they will just have to sit on their blisters.',147,'Abraham Lincoln',0); 151 | INSERT INTO Quotes VALUES('Give me six hours to chop down a tree and I will spend the first four sharpening the axe.',148,'Abraham Lincoln',0); 152 | INSERT INTO Quotes VALUES('No man has a good enough memory to be a successful liar.',149,'Abraham Lincoln',0); 153 | INSERT INTO Quotes VALUES('The best thing about the future is that it comes one day at a time.',150,'Abraham Lincoln',0); 154 | INSERT INTO Quotes VALUES('I have always found that mercy bears richer fruits than strict justice.',151,'Abraham Lincoln',0); 155 | INSERT INTO Quotes VALUES('I care not for a man''s religion whose dog and cat are not the better for it.',152,'Abraham Lincoln',0); 156 | INSERT INTO Quotes VALUES('You cannot escape the responsibility of tomorrow by evading it today.',153,'Abraham Lincoln',0); 157 | INSERT INTO Quotes VALUES('I do not think much of a man who is not wiser today than he was yesterday.',154,'Abraham Lincoln',0); 158 | INSERT INTO Quotes VALUES('You have to do your own growing no matter how tall your grandfather was.',155,'Abraham Lincoln',0); 159 | INSERT INTO Quotes VALUES('You cannot help people permanently by doing for them, what they could and should do for themselves.',156,'Abraham Lincoln',0); 160 | INSERT INTO Quotes VALUES('You can tell the greatness of a man by what makes him angry.',157,'Abraham Lincoln',0); 161 | INSERT INTO Quotes VALUES('When something is important enough, you do it even if the odds are not in your favor.',158,'Elon Musk',0); 162 | INSERT INTO Quotes VALUES('If you get up in the morning and think the future is going to be better, it is a bright day. Otherwise, it''s not.',159,'Elon Musk',0); 163 | INSERT INTO Quotes VALUES('There have to be reasons that you get up in the morning and you want to live. Why do you want to live? What''s the point? What inspires you? What do you love about the future? If the future does not include being out there among the stars and being a multi-planet species, I find that incredibly depressing.',160,'Elon Musk',0); 164 | INSERT INTO Quotes VALUES('When Henry Ford made cheap, reliable cars, people said, ''Nah, what''s wrong with a horse?'' That was a huge bet he made, and it worked.',161,'Elon Musk',0); 165 | INSERT INTO Quotes VALUES('Persistence is very important. You should not give up unless you are forced to give up.',162,'Elon Musk',0); 166 | INSERT INTO Quotes VALUES('It''s OK to have your eggs in one basket as long as you control what happens to that basket.',163,'Elon Musk',0); 167 | INSERT INTO Quotes VALUES('If you go back a few hundred years, what we take for granted today would seem like magic-being able to talk to people over long distances, to transmit images, flying, accessing vast amounts of data like an oracle. These are all things that would have been considered magic a few hundred years ago.',164,'Elon Musk',0); 168 | INSERT INTO Quotes VALUES('The first step is to establish that something is possible; then probability will occur.',165,'Elon Musk',0); 169 | INSERT INTO Quotes VALUES('I think it is possible for ordinary people to choose to be extraordinary.',166,'Elon Musk',0); 170 | INSERT INTO Quotes VALUES('I could either watch it happen or be a part of it.',167,'Elon Musk',0); 171 | INSERT INTO Quotes VALUES('Do one thing every day that scares you.',168,'Eleanor Roosevelt',0); 172 | INSERT INTO Quotes VALUES('Do what you feel in your heart to be right – for you’ll be criticized anyway.',169,'Eleanor Roosevelt',0); 173 | INSERT INTO Quotes VALUES('The future belongs to those who believe in the beauty of their dreams.',170,'Eleanor Roosevelt',0); 174 | INSERT INTO Quotes VALUES('The purpose of life is to live it, to taste experience to the utmost, to reach out eagerly and without fear for newer and richer experience.',171,'Eleanor Roosevelt',0); 175 | INSERT INTO Quotes VALUES('Many people will walk in and out of your life, but only true friends will leave footprints in your heart.',172,'Eleanor Roosevelt',0); 176 | INSERT INTO Quotes VALUES('We are afraid to care too much, for fear that the other person does not care at all.',173,'Eleanor Roosevelt',0); 177 | INSERT INTO Quotes VALUES('To handle yourself, use your head; to handle others, use your heart.',174,'Eleanor Roosevelt',0); 178 | INSERT INTO Quotes VALUES('You can often change your circumstances by changing your attitude.',175,'Eleanor Roosevelt',0); 179 | INSERT INTO Quotes VALUES('If someone betrays you once, it’s their fault; if they betray you twice, it’s your fault.',176,'Eleanor Roosevelt',0); 180 | INSERT INTO Quotes VALUES('With the new day comes new strength and new thoughts.',177,'Eleanor Roosevelt',0); 181 | INSERT INTO Quotes VALUES('Happiness is not a goal...it''s a by-product of a life well lived.',178,'Eleanor Roosevelt',0); 182 | INSERT INTO Quotes VALUES('Life was meant to be lived, and curiosity must be kept alive. One must never, for whatever reason, turn his back on life.',179,'Eleanor Roosevelt',0); 183 | INSERT INTO Quotes VALUES('It is not fair to ask of others what you are not willing to do yourself.',180,'Eleanor Roosevelt',0); 184 | INSERT INTO Quotes VALUES('You have to accept whatever comes, and the only important thing is that you meet it with the best you have to give.',181,'Eleanor Roosevelt',0); 185 | INSERT INTO Quotes VALUES('In the long run, we shape our lives, and we shape ourselves. The process never ends until we die. And the choices we make are ultimately our own responsibility.',182,'Eleanor Roosevelt',0); 186 | INSERT INTO Quotes VALUES('Friendship with oneself is all important, because without it one cannot be friends with anyone else in the world.',183,'Eleanor Roosevelt',0); 187 | INSERT INTO Quotes VALUES('Never allow a person to tell you no who doesn''t have the power to say yes.',184,'Eleanor Roosevelt',0); 188 | INSERT INTO Quotes VALUES('Never mistake knowledge for wisdom. One helps you make a living; the other helps you make a life.',185,'Eleanor Roosevelt',0); 189 | INSERT INTO Quotes VALUES('No one won the last war, and no one will win the next war.',186,'Eleanor Roosevelt',0); 190 | INSERT INTO Quotes VALUES('When will our consciences grow so tender that we will act to prevent human misery rather than avenge it?',187,'Eleanor Roosevelt',0); 191 | INSERT INTO Quotes VALUES('We are not makers of history. We are made by history.',188,'Martin Luther King Jr.',0); 192 | INSERT INTO Quotes VALUES('Every man must decide whether he will walk in the light of creative altruism or in the darkness of destructive selfishness.',189,'Martin Luther King Jr.',0); 193 | INSERT INTO Quotes VALUES('We must use time creatively, in the knowledge that the time is always ripe to do right.',190,'Martin Luther King Jr.',0); 194 | INSERT INTO Quotes VALUES('There is nothing more tragic than to find an individual bogged down in the length of life, devoid of breadth.',191,'Martin Luther King Jr.',0); 195 | INSERT INTO Quotes VALUES('Property is intended to serve life, and no matter how much we surround it with rights and respect, it has no personal being. It is part of the earth man walks on. It is not man.',192,'Martin Luther King Jr.',0); 196 | INSERT INTO Quotes VALUES('The function of education is to teach one to think intensively and to think critically. Intelligence plus character – that is the goal of true education.',193,'Martin Luther King Jr.',0); 197 | INSERT INTO Quotes VALUES('All labor that uplifts humanity has dignity and importance and should be undertaken with painstaking excellence.',194,'Martin Luther King Jr.',0); 198 | INSERT INTO Quotes VALUES('An individual has not started living until he can rise above the narrow confines of his individualistic concerns to the broader concerns of all humanity.',195,'Martin Luther King Jr.',0); 199 | INSERT INTO Quotes VALUES('Rarely do we find men who willingly engage in hard, solid thinking. There is an almost universal quest for easy answers and half-baked solutions. Nothing pains some people more than having to think.',196,'Martin Luther King Jr.',0); 200 | INSERT INTO Quotes VALUES('Every man lives in two realms: the internal and the external. The internal is that realm of spiritual ends expressed in art, literature, morals, and religion. The external is that complex of devices, techniques, mechanisms, and instrumentalities by means of which we live.',197,'Martin Luther King Jr.',0); 201 | INSERT INTO Quotes VALUES('Shallow understanding from people of good will is more frustrating than absolute misunderstanding from people of ill will.',198,'Martin Luther King Jr.',0); 202 | INSERT INTO Quotes VALUES('There comes a time when people get tired of being pushed out of the glittering sunlight of life’s July and left standing amid the piercing chill of an alpine November.',199,'Martin Luther King Jr.',0); 203 | INSERT INTO Quotes VALUES('A lie cannot live.',200,'Martin Luther King Jr.',0); 204 | INSERT INTO Quotes VALUES('The past is prophetic in that it asserts loudly that wars are poor chisels for carving out peaceful tomorrows.',201,'Martin Luther King Jr.',0); 205 | INSERT INTO Quotes VALUES('The limitation of riots, moral questions aside, is that they cannot win and their participants know it. Hence, rioting is not revolutionary but reactionary because it invites defeat. It involves an emotional catharsis, but it must be followed by a sense of futility.',202,'Martin Luther King Jr.',0); 206 | INSERT INTO Quotes VALUES('He who is devoid of the power to forgive is devoid of the power to love.',203,'Martin Luther King Jr.',0); 207 | INSERT INTO Quotes VALUES('I believe that unarmed truth and unconditional love will have the final word in reality. This is why right, temporarily defeated, is stronger than evil triumphant.',204,'Martin Luther King Jr.',0); 208 | INSERT INTO Quotes VALUES('The grass is greener on the other side of the fence.',205,'Anonymous',0); 209 | INSERT INTO Quotes VALUES('After ~1000 failed coding projects, we''ve learned one thing: Most coding projects are a waste of time.',206,'QB Devs',0); 210 | INSERT INTO Quotes VALUES('When ordering a pizza, a "Thick Crust" option means that the *other* options are way too thin.',207,'QB Devs',0); 211 | INSERT INTO Quotes VALUES('We''re pretty indecisive. Or maybe not. Or maybe we are...',208,'QB Devs',0); 212 | INSERT INTO Quotes VALUES('I have 2 questions. 1) How do we solve climate change? 2) Why are there no B batteries?',209,'QB Devs',0); 213 | INSERT INTO Quotes VALUES('Knowledge is knowing that a tomato is a fruit; wisdom is not putting it in a fruit salad.',210,'Miles Kington',0); 214 | CREATE UNIQUE INDEX main_quotes on Quotes(quote); 215 | CREATE INDEX main_index ON Quotes(quote, source, id); 216 | COMMIT; 217 | --------------------------------------------------------------------------------