├── .env.sample ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── Dockerfile ├── cdn └── avatars │ └── .gitkeep ├── docker-compose.yml ├── emkc ├── license ├── package.json ├── platform ├── .babelrc ├── api │ ├── controllers │ │ ├── AuthController.js │ │ ├── ChallengesController.js │ │ ├── CommunityController.js │ │ ├── ContestsController.js │ │ ├── HomeController.js │ │ ├── MerchController.js │ │ ├── ProfilesController.js │ │ ├── ScriptsController.js │ │ ├── SnippetsController.js │ │ ├── TagsController.js │ │ ├── admin │ │ │ ├── ChallengesController.js │ │ │ ├── ContestsController.js │ │ │ ├── DashboardController.js │ │ │ ├── PistonController.js │ │ │ └── UsersController.js │ │ └── api │ │ │ ├── internal │ │ │ ├── ChatsController.js │ │ │ └── PistonController.js │ │ │ ├── v1 │ │ │ ├── PistonController.js │ │ │ ├── UsersController.js │ │ │ └── stats │ │ │ │ ├── DiscordController.js │ │ │ │ └── PistonController.js │ │ │ └── v2 │ │ │ └── PistonController.js │ ├── policies │ │ ├── api_internal_auth.js │ │ ├── common.js │ │ ├── is_admin.js │ │ ├── is_prod.js │ │ └── logged_in.js │ └── services │ │ ├── api.js │ │ ├── constant.js │ │ ├── contests.js │ │ ├── discord.js │ │ ├── dispenserd.js │ │ ├── error.js │ │ ├── mailer.js │ │ ├── piston.js │ │ ├── test_cases.js │ │ ├── twig.js │ │ ├── util.js │ │ └── views.js ├── config │ ├── blueprints.js │ ├── bootstrap.js │ ├── controllers.js │ ├── http.js │ ├── local.js.sample │ ├── paths.js │ ├── policies.js │ ├── routes.js │ ├── session.js │ ├── sockets.js │ └── views.js ├── console │ ├── common.js │ ├── cron.js │ └── util.js ├── emkc.js ├── migrations │ ├── config.json.sample │ └── migrations │ │ ├── 20180320123747-initial.sql │ │ ├── 20180901170431-triggers.sql │ │ ├── 20180903004942-display-name.sql │ │ ├── 20180903013450-question-tags.sql │ │ ├── 20180903180404-default-avatar.sql │ │ ├── 20180903222426-views-field.sql │ │ ├── 20180905220531-notification-table.sql │ │ ├── 20180908000333-new-tags.sql │ │ ├── 20180915035412-code-rooms.sql │ │ ├── 20180917013146-snippet-language.sql │ │ ├── 20180930153901-video-requests.sql │ │ ├── 20181005005500-challenges-tables.sql │ │ ├── 20181021204739-chats-table.sql │ │ ├── 20181107035714-new-challenge.sql │ │ ├── 20181111035714-new-challenge.sql │ │ ├── 20181119035714-new-challenge.sql │ │ ├── 20181121035714-discord-rank-field.sql │ │ ├── 20181229135021-new-challenge.sql │ │ ├── 20190104235301-new-challenge.sql │ │ ├── 20190405004828-new-challenge.sql │ │ ├── 20190611224428-new-challenge.sql │ │ ├── 20190622133430-new-challenge.sql │ │ ├── 20190622224428-discord-id-chat-messages.sql │ │ ├── 20190624224428-script-town.sql │ │ ├── 20191023224428-stickers.sql │ │ ├── 20191101133430-new-challenge.sql │ │ ├── 20191201133430-new-challenge.sql │ │ ├── 20200711133430-piston-stats.sql │ │ ├── 20200711133431-piston-stats.sql │ │ ├── 20200802133431-new-challenge.sql │ │ ├── 20200813092823-new-challenge.sql │ │ ├── 20200825133432-new-challenge.sql │ │ ├── 20200830224428-contests-tables.sql │ │ ├── 20200905203703-contest-draft-field.sql │ │ ├── 20200918012206-cleanup-old-tables.sql │ │ ├── 20200918012216-award-table.sql │ │ ├── 20210117125516-add-html-to-challenges.sql │ │ ├── 20210117161957-create-tests-table.sql │ │ ├── 20210220201643-piston-run-changes.sql │ │ ├── 20210314201643-challenge-draft.sql │ │ ├── 20210319145442-add-disallowed-languages.sql │ │ ├── 20210325110214-change-character-set.sql │ │ ├── 20210326154806-add-late-submissions.sql │ │ ├── 20210401114642-add-explanation-field.sql │ │ ├── 20210423100104-add-language-version.sql │ │ ├── 20210714100104-add-best-length.sql │ │ ├── 20210901095201-remove-contest-draft-field.sql │ │ ├── 20220706141314-drop-challenges-folder.sql │ │ └── 20220707092911-drop-official-field.sql ├── models │ ├── awards.js │ ├── challenge_tests.js │ ├── challenges.js │ ├── cli_scripts.js │ ├── contest_submissions.js │ ├── contests.js │ ├── discord_chat_messages.js │ ├── index.js │ ├── piston_runs.js │ ├── snippets.js │ ├── sticker_orders.js │ ├── tags.js │ ├── user_challenges.js │ └── users.js ├── package.json ├── pm2.json ├── public │ ├── cdn │ ├── css │ │ └── .gitkeep │ ├── images │ │ ├── 404.png │ │ ├── 502_animated.gif │ │ ├── awards │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ ├── 4.png │ │ │ └── 5.png │ │ ├── icon_circle_24.png │ │ ├── icon_circle_64.png │ │ ├── icon_square_64.png │ │ ├── lang_icons │ │ │ ├── easy │ │ │ │ ├── bash.svg │ │ │ │ ├── brainfuck.svg │ │ │ │ ├── c.svg │ │ │ │ ├── cpp.svg │ │ │ │ ├── cs.svg │ │ │ │ ├── go.svg │ │ │ │ ├── haskell.svg │ │ │ │ ├── java.svg │ │ │ │ ├── jelly.svg │ │ │ │ ├── js.svg │ │ │ │ ├── julia.svg │ │ │ │ ├── kotlin.svg │ │ │ │ ├── nim.svg │ │ │ │ ├── perl.svg │ │ │ │ ├── php.svg │ │ │ │ ├── python.svg │ │ │ │ ├── ruby.svg │ │ │ │ ├── rust.svg │ │ │ │ ├── scala.svg │ │ │ │ └── swift.svg │ │ │ ├── hard │ │ │ │ ├── bash.svg │ │ │ │ ├── brainfuck.svg │ │ │ │ ├── c.svg │ │ │ │ ├── cpp.svg │ │ │ │ ├── cs.svg │ │ │ │ ├── go.svg │ │ │ │ ├── haskell.svg │ │ │ │ ├── java.svg │ │ │ │ ├── jelly.svg │ │ │ │ ├── js.svg │ │ │ │ ├── julia.svg │ │ │ │ ├── kotlin.svg │ │ │ │ ├── nim.svg │ │ │ │ ├── perl.svg │ │ │ │ ├── php.svg │ │ │ │ ├── python.svg │ │ │ │ ├── ruby.svg │ │ │ │ ├── rust.svg │ │ │ │ ├── scala.svg │ │ │ │ └── swift.svg │ │ │ └── medium │ │ │ │ ├── bash.svg │ │ │ │ ├── brainfuck.svg │ │ │ │ ├── c.svg │ │ │ │ ├── cpp.svg │ │ │ │ ├── cs.svg │ │ │ │ ├── go.svg │ │ │ │ ├── haskell.svg │ │ │ │ ├── java.svg │ │ │ │ ├── jelly.svg │ │ │ │ ├── js.svg │ │ │ │ ├── julia.svg │ │ │ │ ├── kotlin.svg │ │ │ │ ├── nim.svg │ │ │ │ ├── perl.svg │ │ │ │ ├── php.svg │ │ │ │ ├── python.svg │ │ │ │ ├── ruby.svg │ │ │ │ ├── rust.svg │ │ │ │ ├── scala.svg │ │ │ │ └── swift.svg │ │ └── sticker_2019.png │ ├── js │ │ └── .gitkeep │ ├── lib │ │ ├── bootbox │ │ │ └── bootbox.js │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.js │ │ ├── highlightjs │ │ │ ├── atom-one-dark.css │ │ │ ├── default.css │ │ │ ├── highlight-ln.js │ │ │ └── highlight.pack.js │ │ ├── jquery │ │ │ └── jquery-3.0.0.min.js │ │ ├── popper │ │ │ └── popper.min.js │ │ └── webpack │ │ │ └── .gitkeep │ └── other │ │ └── .gitkeep ├── resources │ ├── challenges │ │ └── templates │ │ │ ├── template.c │ │ │ ├── template.cpp │ │ │ ├── template.cs │ │ │ ├── template.go │ │ │ ├── template.hs │ │ │ ├── template.java │ │ │ ├── template.jl │ │ │ ├── template.js │ │ │ ├── template.kt │ │ │ ├── template.nim │ │ │ ├── template.php │ │ │ ├── template.pl │ │ │ ├── template.py │ │ │ ├── template.rb │ │ │ ├── template.rs │ │ │ ├── template.sh │ │ │ └── template.swift │ ├── js │ │ ├── .gitkeep │ │ ├── challenges │ │ │ └── get_language_version.js │ │ ├── common.js │ │ ├── snippets │ │ │ └── delete_snippet.js │ │ └── util.js │ ├── jsx │ │ ├── challenges │ │ │ ├── challenge.jsx │ │ │ └── manage_challenge.jsx │ │ ├── cli_script.jsx │ │ ├── contests │ │ │ ├── contest.jsx │ │ │ ├── description.jsx │ │ │ └── manage.jsx │ │ ├── login.jsx │ │ ├── manage_snippet.jsx │ │ ├── mobile_nav.jsx │ │ ├── ppman.jsx │ │ ├── stickers.jsx │ │ └── users.jsx │ ├── less │ │ ├── bootstrap.less │ │ ├── colors.less │ │ ├── em │ │ │ ├── challenge.less │ │ │ ├── challenge_abstract.less │ │ │ ├── challenge_manage.less │ │ │ ├── challenges_list.less │ │ │ ├── common_content.less │ │ │ ├── community_map.less │ │ │ ├── container.less │ │ │ ├── contests │ │ │ │ ├── contest.less │ │ │ │ ├── home.less │ │ │ │ └── manage.less │ │ │ ├── footer.less │ │ │ ├── language_choice.less │ │ │ ├── login.less │ │ │ ├── manage_snippet.less │ │ │ ├── menu.less │ │ │ ├── mobile_nav.less │ │ │ ├── power_system.less │ │ │ ├── profile.less │ │ │ ├── staff_container.less │ │ │ ├── stickers.less │ │ │ └── top_members.less │ │ ├── global.less │ │ ├── highlightjs.less │ │ └── quill.less │ ├── main.js │ ├── monaco.js │ └── twig │ │ └── filters.js ├── start ├── views │ ├── _emails │ │ └── new_user.twig │ ├── admin │ │ ├── challenges │ │ │ ├── update.twig │ │ │ └── view_all.twig │ │ ├── contests │ │ │ ├── update.twig │ │ │ └── view_all.twig │ │ ├── dashboard │ │ │ └── dashboard.twig │ │ ├── piston │ │ │ └── view_all.twig │ │ └── users │ │ │ └── view_all.twig │ ├── challenges │ │ ├── challenge.twig │ │ ├── choose_language.twig │ │ └── home.twig │ ├── community │ │ ├── about.twig │ │ ├── home.twig │ │ └── power.twig │ ├── contests │ │ ├── contest.twig │ │ └── home.twig │ ├── home │ │ ├── fourohfour.twig │ │ ├── home.twig │ │ ├── login.twig │ │ └── privacy.twig │ ├── master.twig │ ├── merch │ │ └── stickers.twig │ ├── profiles │ │ └── view.twig │ ├── scripts │ │ ├── home.twig │ │ └── view.twig │ └── snippets │ │ ├── edit.twig │ │ └── mine.twig └── webpack.config.js ├── readme.md └── var ├── 502 └── 502.html ├── artwork └── logicons │ ├── c# │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.png │ ├── c++ │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.png │ ├── c │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.png │ ├── dev.png │ ├── go │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.png │ ├── ignore.afdesign │ ├── java │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.jpg │ ├── javascript │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.png │ ├── php │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.png │ ├── python │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.png │ ├── ruby │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.png │ ├── rust │ └── rust.svg │ └── swift │ ├── bg.png │ ├── bg.svg │ ├── nbg.png │ ├── nbg.svg │ └── ref.svg ├── docker ├── clean ├── config │ └── mysqld.cnf ├── init │ └── db.sql ├── logs │ └── .gitkeep ├── mysql │ └── .gitkeep └── redis │ └── .gitkeep ├── felix ├── 404felix.psd ├── blue-robot-vector-art.png └── default.png ├── text └── a.txt └── tmp ├── .gitkeep ├── scripts.sql ├── stats.sql └── vids.sql /.env.sample: -------------------------------------------------------------------------------- 1 | COMPOSE_PROJECT_NAME=emkc 2 | APPENV=production 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | platform/config/local.js 2 | platform/migrations/config.json 3 | platform/public/css/*.css 4 | platform/public/lib/webpack/* 5 | !platform/public/lib/webpack/.gitkeep 6 | cdn/avatars/* 7 | !cdn/avatars/.gitkeep 8 | var/docker/mysql/* 9 | !var/docker/mysql/.gitkeep 10 | var/docker/redis/* 11 | !var/docker/redis/.gitkeep 12 | var/docker/logs/* 13 | !var/docker/logs/.gitkeep 14 | node_modules 15 | package-lock.json 16 | .env 17 | .DS_STORE 18 | .vscode 19 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | platform/config/local.js 2 | platform/migrations/config.json 3 | platform/public/css/*.css 4 | platform/public/lib 5 | platform/resources/challenges/templates 6 | cdn/avatars/* 7 | var/ 8 | node_modules 9 | package-lock.json 10 | .env 11 | .DS_STORE 12 | .vscode 13 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "singleQuote": true, 4 | "trailingComma": "none" 5 | } 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14.3.0-stretch 2 | 3 | RUN apt update && apt install -y inotify-tools libjson-c-dev 4 | RUN cd /opt && \ 5 | wget https://github.com/realtux/rmig/releases/download/0.0.3/rmig-0.0.3-linux && \ 6 | chmod +x rmig-0.0.3-linux && \ 7 | ln -s /opt/rmig-0.0.3-linux /usr/bin/rmig 8 | 9 | WORKDIR /opt/emkc/platform 10 | 11 | CMD ./start 12 | -------------------------------------------------------------------------------- /cdn/avatars/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/cdn/avatars/.gitkeep -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | emkc: 4 | container_name: emkc 5 | build: . 6 | ports: 7 | - '2005:2727' 8 | volumes: 9 | - ./:/opt/emkc 10 | environment: 11 | APPENV: '${APPENV}' 12 | restart: always 13 | depends_on: 14 | - redis 15 | - mysql 16 | redis: 17 | container_name: emkc_redis 18 | image: redis:3.2.12 19 | volumes: 20 | - ./:/opt/emkc 21 | - ./var/docker/redis:/data 22 | restart: always 23 | mysql: 24 | container_name: emkc_mysql 25 | image: mysql:8 26 | environment: 27 | MYSQL_ROOT_PASSWORD: root 28 | MYSQL_DATABASE: emkc 29 | command: --init-file /var/lib/init/db.sql 30 | volumes: 31 | - ./:/opt/emkc 32 | - ./var/docker/mysql:/var/lib/mysql 33 | - ./var/docker/init:/var/lib/init 34 | - ./var/docker/config:/etc/mysql/conf.d 35 | restart: always 36 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2019 Brian Seymour, EMKC Contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "lint": "prettier --write .", 4 | "check-lint": "prettier --check ." 5 | }, 6 | "devDependencies": { 7 | "prettier": "2.7.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /platform/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"], 3 | "plugins": [ 4 | "@babel/plugin-proposal-object-rest-spread", 5 | "@babel/plugin-proposal-class-properties", 6 | "@babel/plugin-transform-async-to-generator" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /platform/api/controllers/CommunityController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | home(req, res) { 3 | return res.view(); 4 | }, 5 | 6 | about(req, res) { 7 | return res.view(); 8 | }, 9 | 10 | power(req, res) { 11 | return res.view(); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /platform/api/controllers/HomeController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | async home(req, res) { 3 | let users = await db.users.find_all({ 4 | order: [['score', 'desc'], ['user_id']], 5 | limit: 100 6 | }); 7 | 8 | return res.view({ 9 | users 10 | }); 11 | }, 12 | 13 | privacy(req, res) { 14 | return res.view(); 15 | }, 16 | 17 | login() { 18 | return res.view(); 19 | }, 20 | 21 | async logout_as(req, res) { 22 | if (!req.session.old_id) { 23 | // Logging back from nothing 24 | return res.view('home/fourohfour'); 25 | } 26 | 27 | req.session.user_id = req.session.old_id; 28 | delete req.session.old_id; 29 | 30 | return res.redirect('/'); 31 | }, 32 | 33 | logout(req, res) { 34 | delete req.session.user_id; 35 | return res.redirect('back'); 36 | }, 37 | 38 | fourohfour(req, res) { 39 | return res.status(404).view('home/fourohfour'); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /platform/api/controllers/MerchController.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment'); 2 | 3 | module.exports = { 4 | stickers(req, res) { 5 | return res.view({ 6 | options: [ 7 | { quantity: 2, cost: 'FREE' }, 8 | { quantity: 3, cost: '2.40' }, 9 | { quantity: 5, cost: '3.50' }, 10 | { quantity: 10, cost: '6.00' } 11 | ] 12 | }); 13 | }, 14 | 15 | async order_stickers(req, res) { 16 | const { tx, quantity, name, email, address, coupon } = req.body; 17 | 18 | if (!coupon && !tx) { 19 | return res.status(400).send(); 20 | } 21 | 22 | let order = await db.sticker_orders.create({ 23 | tx, 24 | coupon, 25 | quantity, 26 | cost: { 27 | 2: null, 28 | 3: 2.4, 29 | 5: 3.5, 30 | 10: 6.0 31 | }[quantity], 32 | name, 33 | email, 34 | address, 35 | created_at: moment() 36 | }); 37 | 38 | return res.status(200).send({ 39 | order_id: order.sticker_order_id 40 | }); 41 | }, 42 | 43 | check_code(req, res) { 44 | return res.status(200).send({ 45 | valid: 46 | req.params.code.to_upper_case() === sails.config.paypal.coupon 47 | }); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /platform/api/controllers/ScriptsController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | async home(req, res) { 3 | let scripts = await db.cli_scripts.find_all({ 4 | where: { 5 | is_safe: constant.yes 6 | } 7 | }); 8 | 9 | return res.view({ 10 | scripts 11 | }); 12 | }, 13 | 14 | async view(req, res) { 15 | const cli_script_id = req.params.cli_script_id; 16 | 17 | let script = await db.cli_scripts.find_one({ 18 | where: { 19 | cli_script_id 20 | } 21 | }); 22 | 23 | return res.view({ 24 | script 25 | }); 26 | }, 27 | 28 | async exec(req, res) { 29 | const cli_script_id = req.params.cli_script_id; 30 | 31 | let script = await db.cli_scripts.find_one({ 32 | where: { 33 | cli_script_id 34 | } 35 | }); 36 | 37 | res.set('content-type', 'text/plain'); 38 | 39 | return res.status(200).send(script.content); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /platform/api/controllers/TagsController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | async search(req, res) { 3 | const name = req.query.name; 4 | 5 | let tags = await db.tags.find_all({ 6 | where: { 7 | name: { 8 | [$like]: '%' + name + '%' 9 | } 10 | }, 11 | order: [['name']], 12 | limit: 10 13 | }); 14 | 15 | return res.send({ 16 | status: 'ok', 17 | payload: { 18 | tags: name ? tags : [] 19 | } 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /platform/api/controllers/admin/DashboardController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | async dashboard(req, res) { 3 | return res.view(); 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /platform/api/controllers/admin/PistonController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | async view_all(req, res) { 3 | return res.view({ 4 | message: null 5 | }); 6 | }, 7 | 8 | async packages(req, res) { 9 | let packages = await piston.packages(); 10 | 11 | return res.status(200).send(packages); 12 | }, 13 | 14 | async install(req, res) { 15 | let { language, version } = req.query; 16 | 17 | let result = await piston.install(language, version); 18 | 19 | let message = result.language 20 | ? 'succeeded' 21 | : 'failed: ' + result.message; 22 | 23 | return res.view('admin/piston/view_all', { 24 | message: `Installation of ${language}-${version} ${message}` 25 | }); 26 | }, 27 | 28 | async uninstall(req, res) { 29 | let { language, version } = req.query; 30 | 31 | let result = await piston.uninstall(language, version); 32 | 33 | let message = result.language 34 | ? 'succeeded' 35 | : 'failed: ' + result.message; 36 | 37 | return res.view('admin/piston/view_all', { 38 | message: `Uninstallation of ${language}-${version} ${message}` 39 | }); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /platform/api/controllers/admin/UsersController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | async view_all(req, res) { 3 | let users = await db.users.find_all({ 4 | attributes: ['user_id', 'username', 'display_name', 'created_at'], 5 | where: { 6 | [$not]: { 7 | user_id: req.session.user_id 8 | } 9 | }, 10 | order: [['user_id', 'desc']] 11 | }); 12 | 13 | return res.view({ 14 | users 15 | }); 16 | }, 17 | 18 | async login_as(req, res) { 19 | let target_id = parse_int(req.query.user_id); 20 | 21 | let user = await db.users.find_one({ 22 | where: { 23 | user_id: target_id 24 | } 25 | }); 26 | 27 | // The logging in logic 28 | if (req.session.user_id === target_id || req.session.old_id || !user) { 29 | // On trying to log in as oneself or not using the original user 30 | return res.view('home/fourohfour'); 31 | } 32 | 33 | req.session.old_id = req.session.user_id; 34 | req.session.user_id = target_id; 35 | 36 | return res.redirect('/'); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /platform/api/controllers/api/internal/PistonController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | async log(req, res) { 3 | let { server, server_id, user, user_id, language, source } = req.body; 4 | 5 | if ( 6 | !server || 7 | !server_id || 8 | !user || 9 | !user_id || 10 | !language || 11 | !source 12 | ) { 13 | return res.status(400).send(); 14 | } 15 | 16 | await db.piston_runs.create({ 17 | server, 18 | server_id, 19 | user, 20 | user_id, 21 | language, 22 | source 23 | }); 24 | 25 | return res.status(200).send(); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /platform/api/controllers/api/v1/UsersController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | async read_all(req, res) { 3 | const { discord_id } = req.query; 4 | 5 | let query = { 6 | where: {}, 7 | attributes: [ 8 | 'user_id', 9 | 'discord_api', 10 | 'username', 11 | 'display_name', 12 | 'score' 13 | ] 14 | }; 15 | 16 | if (discord_id) { 17 | query.where.discord_api = discord_id; 18 | } 19 | 20 | let users = await db.users.find_all(query); 21 | 22 | return res.status(200).send(users); 23 | }, 24 | 25 | async read(req, res) { 26 | const user_id = req.params.user_id; 27 | 28 | let user = await db.users.find_one({ 29 | where: { 30 | user_id 31 | }, 32 | attributes: ['user_id', 'username', 'display_name', 'score'] 33 | }); 34 | 35 | if (!user) { 36 | return res.status(404).send(); 37 | } 38 | 39 | return res.status(200).send(user); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /platform/api/controllers/api/v1/stats/PistonController.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment'); 2 | 3 | module.exports = { 4 | async usage(req, res) { 5 | let { start, end, category } = req.query; 6 | 7 | let query = { 8 | where: { 9 | [$and]: [] 10 | } 11 | }; 12 | 13 | let where = query.where[$and]; 14 | 15 | switch (category) { 16 | case 'bot': 17 | where.push({ 18 | server_id: { 19 | [$ne]: null 20 | } 21 | }); 22 | break; 23 | case 'emkc': 24 | where.push({ 25 | server_id: null 26 | }); 27 | where.push({ 28 | server: 'EMKC' 29 | }); 30 | break; 31 | case 'direct': 32 | where.push({ 33 | server_id: null 34 | }); 35 | where.push({ 36 | server: 'Piston API' 37 | }); 38 | break; 39 | } 40 | 41 | if (start) { 42 | start = moment(start); 43 | 44 | if (start.isValid()) { 45 | where.push({ 46 | created_at: { 47 | [$gte]: start.format('YYYY-MM-DD HH:mm:ss') 48 | } 49 | }); 50 | } 51 | } 52 | 53 | if (end) { 54 | end = moment(end); 55 | 56 | if (end.isValid()) { 57 | where.push({ 58 | created_at: { 59 | [$lte]: end.format('YYYY-MM-DD HH:mm:ss') 60 | } 61 | }); 62 | } 63 | } 64 | 65 | let count = await db.piston_runs.count(query); 66 | 67 | return res.status(200).send({ 68 | count 69 | }); 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /platform/api/policies/api_internal_auth.js: -------------------------------------------------------------------------------- 1 | module.exports = (req, res, next) => { 2 | let authorization; 3 | 4 | Object.keys(req.headers).for_each((key) => { 5 | if (key.to_lower_case() === 'authorization') 6 | authorization = req.headers[key]; 7 | }); 8 | 9 | if (authorization !== sails.config.api.internal_key) { 10 | return res.send(401, { 11 | message: 'Invalid authorization' 12 | }); 13 | } 14 | 15 | return next(); 16 | }; 17 | -------------------------------------------------------------------------------- /platform/api/policies/common.js: -------------------------------------------------------------------------------- 1 | module.exports = async (req, res, next) => { 2 | req.local = req.local || { user_id: null }; 3 | 4 | req.local.constant = constant; 5 | 6 | // get the logged in user 7 | let user = await db.users.find_one({ 8 | where: { 9 | user_id: req.session.user_id || null 10 | } 11 | }); 12 | 13 | if (user) { 14 | req.local.user_id = user.user_id; 15 | req.local.user = user; 16 | } 17 | 18 | return next(); 19 | }; 20 | -------------------------------------------------------------------------------- /platform/api/policies/is_admin.js: -------------------------------------------------------------------------------- 1 | module.exports = (req, res, next) => { 2 | if (!req.local.user || !req.local.user.is_staff) { 3 | return res.redirect('/'); 4 | } 5 | 6 | return next(); 7 | }; 8 | -------------------------------------------------------------------------------- /platform/api/policies/is_prod.js: -------------------------------------------------------------------------------- 1 | module.exports = (req, res, next) => { 2 | if (!constant.is_prod) { 3 | return res.redirect('/'); 4 | } 5 | 6 | return next(); 7 | }; 8 | -------------------------------------------------------------------------------- /platform/api/policies/logged_in.js: -------------------------------------------------------------------------------- 1 | module.exports = (req, res, next) => { 2 | if (!req.local.user_id) return res.redirect('/'); 3 | return next(); 4 | }; 5 | -------------------------------------------------------------------------------- /platform/api/services/api.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | handle_err(res, err) { 3 | console.log(err, '\n\n'); 4 | 5 | try { 6 | err = JSON.parse(err.message); 7 | 8 | return res.send({ 9 | message: err[0] || 'An error occurred', 10 | errors: err[1] 11 | }); 12 | } catch (e) { 13 | return res.send({ 14 | message: err.message || 'An error occurred' 15 | }); 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /platform/api/services/discord.js: -------------------------------------------------------------------------------- 1 | const request = require('request-promise'); 2 | 3 | module.exports = { 4 | async api(method, url, body = null) { 5 | const options = { 6 | method, 7 | url: 'https://discord.com/api/v10' + url, 8 | headers: { 9 | Authorization: 'Bot ' + sails.config.felix.key 10 | }, 11 | json: true, 12 | simple: false, 13 | resolveWithFullResponse: true 14 | }; 15 | 16 | if (body) { 17 | options.body = body; 18 | } 19 | 20 | const response = await request(options); 21 | 22 | return response; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /platform/api/services/dispenserd.js: -------------------------------------------------------------------------------- 1 | const request = require('request-promise'); 2 | 3 | module.exports = { 4 | lane_main: 'main', 5 | 6 | job_test: 'test', 7 | 8 | /** 9 | * dispenserd.schedule(dispenserd.job_test, { 10 | * key: 'value' 11 | * }); 12 | */ 13 | schedule(job, options) { 14 | options.job = job; 15 | 16 | request 17 | .post({ 18 | url: 19 | 'http://' + sails.config.dispenserd.host + ':8282/schedule', 20 | body: JSON.stringify({ 21 | lane: options.lane || dispenserd.lane_main, 22 | priority: options.priority || 10000, 23 | message: JSON.stringify(options) 24 | }), 25 | resolveWithFullResponse: true, 26 | simple: false 27 | }) 28 | .catch((err) => { 29 | console.log('job failed to schedule'); 30 | }); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /platform/api/services/error.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment'); 2 | 3 | module.exports = { 4 | log(err, msg) { 5 | var final_message = '[msg] ' + msg + '\n' + '[date] ' + util.now(); 6 | 7 | if (err) { 8 | final_message += '\n[err] ' + err.toString(); 9 | } 10 | 11 | console.log('\n---\n' + final_message); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /platform/api/services/mailer.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment'); 2 | const q = require('q'); 3 | const mailgun = require('mailgun-js')({ 4 | apiKey: sails.config.mailgun.key, 5 | domain: sails.config.mailgun.domain 6 | }); 7 | 8 | module.exports = { 9 | send(to, subject, content, template, variables) { 10 | var final_content; 11 | 12 | var from = variables.context.name + ' '; 13 | 14 | subject = subject.replace('{{name}}', variables.context.name); 15 | 16 | var send = () => { 17 | mailgun.messages().send( 18 | { 19 | from, 20 | to: constant.email_intercept || to, 21 | 'h:Reply-to': variables.reply_to || 'no-reply@emkc.org', 22 | subject, 23 | html: final_content 24 | }, 25 | (err, body) => { 26 | try { 27 | console.log('email to: ' + to); 28 | console.log('subject: ' + subject); 29 | console.log('err: ' + err); 30 | console.log('body: ' + JSON.stringify(body)); 31 | } catch (e) { 32 | console.log('in catch'); 33 | } 34 | } 35 | ); 36 | }; 37 | 38 | if (template) { 39 | views.render(template, variables).then((template_content) => { 40 | final_content = template_content; 41 | send(); 42 | }); 43 | } else { 44 | final_content = content; 45 | send(); 46 | } 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /platform/api/services/test_cases.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get_inputs_and_outputs(test_object) { 3 | const inputs = test_object.input 4 | .split('\n') 5 | .map((input) => input.split('|')); 6 | const outputs = test_object.output.split('\n'); 7 | return { inputs, outputs }; 8 | }, 9 | 10 | are_valid(test_object) { 11 | return ( 12 | test_object.input !== '' && 13 | test_object.output !== '' && 14 | test_object.input.split('\n').length === 15 | test_object.output.split('\n').length 16 | ); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /platform/api/services/twig.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment'); 2 | 3 | const twig = require('twig'); 4 | 5 | twig.extendFilter('noscript', (value) => { 6 | if (!value) { 7 | return value; 8 | } 9 | 10 | return value.replace(/\//gi, '\\/'); 11 | }); 12 | 13 | module.exports = { 14 | starts_with(string, path) { 15 | let pattern = new RegExp('^' + path.replace('/', '\\/')); 16 | 17 | return pattern.test(string); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /platform/api/services/views.js: -------------------------------------------------------------------------------- 1 | const twig = require('twig'); 2 | 3 | module.exports = { 4 | async render(template, data) { 5 | data.sails = sails; 6 | data.constant = constant; 7 | 8 | return await twig 9 | .twig({ 10 | allowInlineIncludes: true, 11 | base: root_dir + '/platform/views', 12 | path: root_dir + '/platform/views/' + template + '.twig', 13 | async: false 14 | }) 15 | .render(data); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /platform/config/blueprints.js: -------------------------------------------------------------------------------- 1 | module.exports.blueprints = { 2 | actions: false, 3 | shortcuts: false, 4 | rest: false, 5 | index: false 6 | }; 7 | -------------------------------------------------------------------------------- /platform/config/bootstrap.js: -------------------------------------------------------------------------------- 1 | process.env.TZ = 'UTC'; 2 | 3 | require('nocamel'); 4 | 5 | const path = require('path'); 6 | root_dir = path.resolve(__dirname + '/../../'); 7 | 8 | Promise = require('bluebird'); 9 | 10 | let axios = require('axios'); 11 | axios.defaults.validateStatus = () => true; 12 | 13 | module.exports.bootstrap = (cb) => { 14 | db = require(root_dir + '/platform/models/index.js'); 15 | 16 | sails.local = { root_dir }; 17 | sails.twig = require(root_dir + '/platform/api/services/twig.js'); 18 | sails.local.constant = require(root_dir + 19 | '/platform/api/services/constant.js'); 20 | sails.local.epoch = +new Date(); 21 | 22 | sails.io.sockets.on('connection', (socket) => { 23 | // test for code room socket 24 | var hash = /\/r\/([a-zA-Z0-9]+)/gi.exec( 25 | socket.handshake.headers.referer 26 | ); 27 | hash = hash.length > 1 ? hash[1] : null; 28 | 29 | if (hash) return code_rooms.handle_socket_actions(socket, hash); 30 | }); 31 | 32 | cb(); 33 | }; 34 | -------------------------------------------------------------------------------- /platform/config/controllers.js: -------------------------------------------------------------------------------- 1 | module.exports.controllers = { 2 | blueprints: { 3 | actions: false, 4 | rest: false, 5 | shortcuts: false, 6 | prefix: '', 7 | pluralize: false 8 | }, 9 | 10 | jsonp: false, 11 | expectIntegerId: false 12 | }; 13 | -------------------------------------------------------------------------------- /platform/config/http.js: -------------------------------------------------------------------------------- 1 | module.exports.http = { 2 | middleware: { 3 | xframe: require('lusca').xframe('SAMEORIGIN'), 4 | order: [ 5 | 'startRequestTimer', 6 | 'xframe', 7 | 'cookieParser', 8 | 'session', 9 | 'bodyParser', 10 | 'test_json', 11 | 'compress', 12 | 'methodOverride', 13 | '$custom', 14 | 'router', 15 | 'www', 16 | 'favicon', 17 | '404', 18 | '500' 19 | ], 20 | test_json(err, req, res, next) { 21 | if (err) { 22 | return res.send(400, { 23 | message: 'Invalid JSON received' 24 | }); 25 | } 26 | 27 | return next(); 28 | } 29 | }, 30 | 31 | bodyParser() { 32 | return require('skipper')({ limit: '4096mb' }); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /platform/config/local.js.sample: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | port: 2727, 4 | environment: 'development', 5 | base_url: 'http://127.0.0.1:2005', 6 | db: { 7 | username: 'root', 8 | password: 'root', 9 | database: 'emkc', 10 | host: 'mysql', 11 | dialect: 'mysql', 12 | logging: false, 13 | timezone: '+00:00', 14 | define: { 15 | underscored: true, 16 | timestamps: false 17 | } 18 | }, 19 | api: { 20 | internal_key: '' 21 | }, 22 | discord: { 23 | client_id: '496807648289882112', 24 | client_secret: 'IqJEUGdYR2UxHKrVmVTha__3aLhIC68l' 25 | }, 26 | felix: { 27 | key: '' 28 | }, 29 | gcp: { 30 | project_id: '' 31 | }, 32 | mailgun: { 33 | key: 'yourkeyhere', 34 | domain: '' 35 | }, 36 | paypal: { 37 | id: '', 38 | secret: '', 39 | coupon: '' 40 | }, 41 | paypal: { 42 | id: '', 43 | secret: '', 44 | coupon: '' 45 | }, 46 | piston: { 47 | host: '127.0.0.1:2000', 48 | unlimited_keys: [] 49 | }, 50 | dispenserd: { 51 | host: '127.0.0.1' 52 | }, 53 | session: { 54 | host: 'redis', 55 | secret: '' 56 | }, 57 | sockets: { 58 | host: 'redis' 59 | } 60 | 61 | }; 62 | -------------------------------------------------------------------------------- /platform/config/paths.js: -------------------------------------------------------------------------------- 1 | module.exports.paths = { 2 | public: __dirname + '/../public' 3 | }; 4 | -------------------------------------------------------------------------------- /platform/config/session.js: -------------------------------------------------------------------------------- 1 | module.exports.session = { 2 | adapter: 'redis', 3 | key: 'engineerman.sid', 4 | cookie: { 5 | maxAge: 60 * 60 * 24 * 20 * 1000 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /platform/config/sockets.js: -------------------------------------------------------------------------------- 1 | module.exports.sockets = { 2 | adapter: 'socket.io-redis' 3 | // transports: ['websocket'] 4 | }; 5 | -------------------------------------------------------------------------------- /platform/config/views.js: -------------------------------------------------------------------------------- 1 | const twig = require('twig'); 2 | 3 | for (let filter of require('../resources/twig/filters')) { 4 | twig.extendFilter(filter.name, filter.filter); 5 | } 6 | 7 | module.exports.views = { 8 | layout: false, 9 | engine: { 10 | ext: 'twig', 11 | fn: twig.__express 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /platform/console/common.js: -------------------------------------------------------------------------------- 1 | process.env.TZ = 'UTC'; 2 | process.setMaxListeners(0); 3 | 4 | require('nocamel'); 5 | 6 | Promise = require('bluebird'); 7 | 8 | root_dir = require('path').resolve(__dirname + '/../../'); 9 | 10 | sails = { 11 | config: require('../config/local.js') 12 | }; 13 | 14 | constant = require('../api/services/constant.js'); 15 | discord = require('../api/services/discord.js'); 16 | dispenserd = require('../api/services/dispenserd.js'); 17 | twig = require('../api/services/twig.js'); 18 | util = require('../api/services/util.js'); 19 | views = require('../api/services/views.js'); 20 | db = require('../models/index.js'); 21 | -------------------------------------------------------------------------------- /platform/console/util.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('./common'); 3 | 4 | const moment = require('moment'); 5 | const request = require('request-promise'); 6 | 7 | let cron = { 8 | ingest_chats() { 9 | let messages = require('fs') 10 | .read_file_sync('chats.log') 11 | .to_string() 12 | .split('\n') 13 | .map((msg) => { 14 | const pieces = msg.split('|'); 15 | 16 | const [timestamp, channel, user] = pieces; 17 | const message = pieces.slice(3).join(''); 18 | 19 | return { 20 | timestamp, 21 | channel, 22 | user, 23 | message 24 | }; 25 | }); 26 | 27 | request({ 28 | method: 'post', 29 | url: 'http://127.0.0.1:2727/api/internal/chats', 30 | headers: { 31 | authorization: sails.config.api.internal_key 32 | }, 33 | body: messages, 34 | json: true, 35 | simple: true 36 | }); 37 | } 38 | }; 39 | 40 | let method = process.argv[2].replace(/-/gi, '_').replace(/^_+/gi, ''); 41 | 42 | cron[method](); 43 | -------------------------------------------------------------------------------- /platform/emkc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Engineer Man Knowledge Center 3 | * Copyright (C) 2021 Brian Seymour and EMKC Contributors 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 | **/ 23 | 24 | require('sails').lift(require('optimist').argv); 25 | -------------------------------------------------------------------------------- /platform/migrations/config.json.sample: -------------------------------------------------------------------------------- 1 | { 2 | "host": "mysql", 3 | "port": 3306, 4 | "user": "root", 5 | "pass": "root", 6 | "db": "emkc", 7 | "platform": "mysql" 8 | } 9 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180901170431-triggers.sql: -------------------------------------------------------------------------------- 1 | up: 2 | drop trigger if exists question_vote_insert_trigger; 3 | delimiter $ 4 | create trigger question_vote_insert_trigger after insert on question_votes for each row begin 5 | update questions set score = score + NEW.value where question_id = NEW.question_id; 6 | end$ 7 | delimiter ; 8 | 9 | drop trigger if exists question_vote_delete_trigger; 10 | delimiter $ 11 | create trigger question_vote_delete_trigger after delete on question_votes for each row begin 12 | update questions set score = score - OLD.value where question_id = OLD.question_id; 13 | end$ 14 | delimiter ; 15 | 16 | drop trigger if exists comment_vote_insert_trigger; 17 | delimiter $ 18 | create trigger comment_vote_insert_trigger after insert on comment_votes for each row begin 19 | update comments set score = score + NEW.value where comment_id = NEW.comment_id; 20 | end$ 21 | delimiter ; 22 | 23 | drop trigger if exists comment_vote_delete_trigger; 24 | delimiter $ 25 | create trigger comment_vote_delete_trigger after delete on comment_votes for each row begin 26 | update comments set score = score - OLD.value where comment_id = OLD.comment_id; 27 | end$ 28 | delimiter ; 29 | 30 | drop trigger if exists comment_insert_trigger; 31 | delimiter $ 32 | create trigger comment_insert_trigger after insert on comments for each row begin 33 | update questions set comments = comments + 1 where question_id = NEW.question_id; 34 | end$ 35 | delimiter ; 36 | 37 | drop trigger if exists comment_delete_trigger; 38 | delimiter $ 39 | create trigger comment_delete_trigger after delete on comments for each row begin 40 | update questions set comments = comments - 1 where question_id = OLD.question_id; 41 | end$ 42 | delimiter ; 43 | 44 | down: 45 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180903004942-display-name.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table users add display_name varchar(64) not null after is_staff; 3 | update users set display_name = username; 4 | 5 | down: 6 | alter table users drop column display_name; 7 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180903013450-question-tags.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table question_tags ( 3 | question_tag_id int unsigned not null auto_increment, 4 | question_id int not null default 0, 5 | tag_id int not null default 0, 6 | primary key (question_tag_id), 7 | key question_id (question_id), 8 | key tag_id (tag_id) 9 | )engine=innodb default charset=utf8; 10 | 11 | down: 12 | drop table question_tags; 13 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180903180404-default-avatar.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table users modify avatar_url varchar(128) not null default '/avatars/default.png' after discord_api; 3 | 4 | down: 5 | alter table users modify avatar_url varchar(128) null after discord_api; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180903222426-views-field.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table questions add views int unsigned not null default 0 after score; 3 | 4 | down: 5 | alter table questions drop column views; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180905220531-notification-table.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table notifications ( 3 | notification_id int unsigned not null auto_increment, 4 | user_id int unsigned not null, 5 | type tinyint unsigned not null, 6 | entity_type tinyint unsigned not null, 7 | entity_id int unsigned not null, 8 | message varchar(512) not null, 9 | created_at datetime not null, 10 | primary key (notification_id), 11 | key user_id (user_id), 12 | key type (type), 13 | key entity_type (entity_type), 14 | key entity_id (entity_id) 15 | )engine=innodb default charset=utf8; 16 | 17 | down: 18 | drop table notifications; 19 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180915035412-code-rooms.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table code_rooms ( 3 | code_room_id int unsigned not null auto_increment, 4 | user_id int unsigned null, 5 | hash varchar(40) not null, 6 | code mediumtext not null, 7 | created_at datetime not null, 8 | primary key (code_room_id), 9 | key user_id (user_id), 10 | key hash (hash), 11 | key created_at (created_at) 12 | )engine=innodb default charset=utf8; 13 | 14 | down: 15 | drop table code_rooms; 16 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180917013146-snippet-language.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table snippets add language varchar(32) not null after hash; 3 | update snippets set language = 'javascript'; 4 | 5 | down: 6 | alter table snippets drop column language; 7 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20180930153901-video-requests.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table video_requests ( 3 | video_request_id int unsigned not null auto_increment, 4 | user_id int not null, 5 | name varchar(255) not null, 6 | created_at datetime not null, 7 | primary key (video_request_id), 8 | key user_id (user_id) 9 | )engine=innodb default charset=utf8; 10 | 11 | create table video_request_votes ( 12 | video_request_vote_id int unsigned not null auto_increment, 13 | video_request_id int unsigned not null, 14 | user_id int unsigned not null, 15 | primary key (video_request_vote_id), 16 | key video_request_id (video_request_id), 17 | key user_id (user_id) 18 | )engine=innodb default charset=utf8; 19 | 20 | down: 21 | drop table video_requests; 22 | drop table video_request_votes; 23 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20181005005500-challenges-tables.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table challenges ( 3 | challenge_id int unsigned not null auto_increment, 4 | difficulty tinyint unsigned not null, 5 | points int unsigned not null, 6 | folder varchar(64) not null, 7 | name varchar(128) not null, 8 | description varchar(512) not null, 9 | primary key (challenge_id), 10 | key difficulty (difficulty), 11 | key points (points) 12 | )engine=innodb default charset=utf8; 13 | 14 | insert into challenges values (1, 1, 10, '1_reverse_string', 'Reverse a string', 'Just take any given string and output it in reverse, pretty easy, right?'); 15 | 16 | create table user_challenges ( 17 | user_challenge_id int unsigned not null auto_increment, 18 | user_id int unsigned not null, 19 | challenge_id int unsigned not null, 20 | language varchar(8) not null, 21 | solution mediumtext not null, 22 | created_at datetime not null, 23 | primary key (user_challenge_id), 24 | key user_id (user_id), 25 | key challenge_id (challenge_id), 26 | key language (language), 27 | key created_at (created_at) 28 | )engine=innodb default charset=utf8; 29 | 30 | down: 31 | drop table challenges; 32 | drop table user_challenges; 33 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20181021204739-chats-table.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table discord_chat_messages ( 3 | discord_chat_message_id int unsigned not null auto_increment, 4 | hash varchar(40) not null, 5 | channel varchar(32) not null, 6 | user varchar(32) not null, 7 | message varchar(8192) not null, 8 | created_at datetime not null, 9 | primary key (discord_chat_message_id), 10 | unique hash (hash), 11 | key channel (channel), 12 | key user (user), 13 | key created_at (created_at) 14 | )engine=innodb default charset=utf8; 15 | 16 | down: 17 | drop table discord_chat_messages; 18 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20181107035714-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (2, 1, 10, '2_number_frequency', 'Count number frequency', 'Take a string of numbers and output the one which appears the most.'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 2; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20181111035714-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (3, 1, 10, '3_list_sum', 'Sum a list of numbers', 'Take a string of comma separated numbers and print out the sum.'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 3; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20181119035714-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (4, 3, 50, '4_invalid_json', 'Detect and fix invalid JSON', 'Take an invalid JSON string and figure out where the errors are and make it valid.'); 3 | insert into challenges values (5, 2, 30, '5_binary_convert', 'Convert string to binary', 'Take three lowercase letters and print out binary.'); 4 | 5 | down: 6 | delete from challenges where challenge_id = 4; 7 | delete from challenges where challenge_id = 5; 8 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20181121035714-discord-rank-field.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table users add discord_rank tinyint unsigned default null after discord_api; 3 | 4 | down: 5 | alter table users drop column discord_rank; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20181229135021-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (6, 2, 30, '6_fibonacci_sequence', 'Fibonacci Numbers', 'Start with one Fibonacci sequence number, then calculate more from there.'); 3 | insert into challenges values (7, 2, 30, '7_check_permutation', 'Check scrambled string', 'Given two strings of equal length, figure out if one is a scramble of the other.'); 4 | 5 | down: 6 | delete from challenges where challenge_id = 6; 7 | delete from challenges where challenge_id = 7; 8 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20190104235301-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (8, 1, 10, '8_sort_integers', 'Integer list sorting', 'Take a list of integers and print it after sorting it in descending order.'); 3 | insert into challenges values (9, 3, 50, '9_roman_numerals', 'Roman Numeral conversion', 'Take a roman numeral(<1000 in value) and print its corresponding value in the decimal system of numbers.'); 4 | 5 | down: 6 | delete from challenges where challenge_id = 8; 7 | delete from challenges where challenge_id = 9; 8 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20190405004828-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (10, 3, 50, '10_pig_latin', 'Pig latin translator', 'Take a sentence/phrase in pig latin, translate it to English.'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 10; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20190611224428-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (11, 2, 30, '11_array_neighbor', 'Zipper merge', 'Merge two arrays in a zipper-like fashion.'); 3 | update challenges set difficulty = 3, points = 50 where challenge_id = 10; 4 | 5 | down: 6 | update challenges set difficulty = 1, points = 10 where challenge_id = 10; 7 | delete from challenges where challenge_id = 11; 8 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20190622133430-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (12, 1, 10, '12_longest_word', 'Find Longest Word', 'Given a string with multiple words, return the longest word.'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 12; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20190622224428-discord-id-chat-messages.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table discord_chat_messages add discord_id varchar(32) not null after user; 3 | alter table discord_chat_messages add index discord_id (discord_id); 4 | 5 | down: 6 | alter table discord_chat_messages drop column discord_id; 7 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20190624224428-script-town.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table cli_scripts ( 3 | cli_script_id int unsigned not null auto_increment, 4 | user_id int unsigned not null, 5 | is_public tinyint unsigned not null default 0, 6 | is_safe tinyint unsigned not null default 0, 7 | title varchar(256) not null, 8 | content mediumtext not null, 9 | created_at datetime not null, 10 | primary key (cli_script_id), 11 | key user_id (user_id), 12 | key is_public (is_public), 13 | key is_safe (is_safe), 14 | key title (title), 15 | key created_at (created_at) 16 | )engine=innodb default charset=utf8; 17 | 18 | down: 19 | drop table cli_scripts; 20 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20191023224428-stickers.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table sticker_orders ( 3 | sticker_order_id int unsigned not null auto_increment, 4 | is_fulfilled tinyint unsigned not null default 0, 5 | tx varchar(128) null, 6 | coupon varchar(128) null, 7 | quantity int unsigned not null, 8 | cost decimal(5,2) null, 9 | name varchar(256) not null, 10 | email varchar(256) not null, 11 | address varchar(256) not null, 12 | created_at datetime not null, 13 | primary key (sticker_order_id), 14 | key is_fulfilled (is_fulfilled), 15 | key created_at (created_at) 16 | )engine=innodb default charset=utf8; 17 | 18 | down: 19 | drop table sticker_orders; 20 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20191101133430-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (13, 2, 30, '13_most_common_character', 'Find Most Common Characters', 'Given a string with multiple words, find the most common character.'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 13; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20191201133430-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (14, 2, 30, '14_number_digit_sum', 'Digit Sum Even or Odd', 'Given a number, find out if the sum of the digits is even or odd.'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 14; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20200711133430-piston-stats.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table piston_runs ( 3 | piston_run_id int unsigned not null auto_increment, 4 | server varchar(64) not null, 5 | user varchar(32) not null, 6 | discord_id varchar(32) not null, 7 | language varchar(32) not null, 8 | source text, 9 | created_at datetime not null, 10 | primary key (piston_run_id), 11 | key server (server), 12 | key user (user), 13 | key discord_id (discord_id), 14 | key language (language), 15 | key created_at (created_at) 16 | )engine=innodb default charset=utf8; 17 | 18 | down: 19 | drop table piston_runs; 20 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20200711133431-piston-stats.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table piston_runs change discord_id user_id varchar(32) not null; 3 | alter table piston_runs add server_id varchar(32) not null after server; 4 | 5 | down: 6 | alter table piston_runs change user_id discord_id varchar(32) not null; 7 | alter table piston_runs drop column server_id; 8 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20200802133431-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (15, 1, 10, '15_binary_cookie', 'Find The Cookie', 'Given a binary string, a cookie, find its place in the binary cookie jar.'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 15; -------------------------------------------------------------------------------- /platform/migrations/migrations/20200813092823-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (16, 1, 10, '16_spiral_corner', 'Spiral Sum', 'Given the size of a spiral, calculate the sum of the four corners.'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 16; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20200825133432-new-challenge.sql: -------------------------------------------------------------------------------- 1 | up: 2 | insert into challenges values (17, 2, 30, '17_quadratic_calculator', 'Answer The Quadratic', 'Given a quadratic find the decimal values of x'); 3 | 4 | down: 5 | delete from challenges where challenge_id = 17; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20200830224428-contests-tables.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table contests ( 3 | contest_id int unsigned not null auto_increment, 4 | name varchar(128) not null, 5 | description mediumtext not null, 6 | start_date datetime not null, 7 | end_date datetime not null, 8 | input text not null, 9 | output text not null, 10 | created_at datetime not null, 11 | primary key (contest_id), 12 | key start_date (start_date), 13 | key end_date (end_date), 14 | key created_at (created_at) 15 | )engine=innodb default charset=utf8; 16 | 17 | insert into contests values (1, 'First Contest', 'Test Description', '2020-08-29 00:00:00', '2020-09-20 23:59:59', '5', '5', now()); 18 | 19 | create table contest_submissions ( 20 | contest_submission_id int unsigned not null auto_increment, 21 | user_id int unsigned not null, 22 | contest_id int unsigned not null, 23 | language varchar(32) not null, 24 | solution mediumtext not null, 25 | length int unsigned not null, 26 | award_place int unsigned null, 27 | award_points int unsigned null, 28 | created_at datetime not null, 29 | primary key (contest_submission_id), 30 | key user_id (user_id), 31 | key contest_id (contest_id), 32 | key language (language), 33 | key award_place (award_place), 34 | key award_points (award_points), 35 | key created_at (created_at) 36 | )engine=innodb default charset=utf8; 37 | 38 | insert into contest_submissions values (default, 1, 1, 'javascript', 'console.log(1)', 14, null, null, now()); 39 | 40 | down: 41 | drop table contests; 42 | drop table contest_submissions; 43 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20200905203703-contest-draft-field.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table contests add draft tinyint unsigned not null default 1 after contest_id; 3 | 4 | down: 5 | alter table contests drop column draft; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20200918012216-award-table.sql: -------------------------------------------------------------------------------- 1 | up: 2 | create table awards ( 3 | award_id int unsigned not null auto_increment, 4 | type int unsigned not null, 5 | points int unsigned not null, 6 | user_id int unsigned not null, 7 | ref_type int unsigned null, 8 | ref_id int unsigned null, 9 | created_at datetime not null, 10 | primary key (award_id), 11 | key type (type), 12 | key points (points), 13 | key user_id (user_id), 14 | key ref_type (ref_type), 15 | key ref_id (ref_id), 16 | key created_at (created_at) 17 | )engine=innodb default charset=utf8; 18 | 19 | down: 20 | drop table awards; 21 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210220201643-piston-run-changes.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table piston_runs modify server_id varchar(32) null; 3 | alter table piston_runs modify user_id varchar(32) null; 4 | 5 | down: 6 | 7 | alter table piston_runs modify server_id varchar(32) not null; 8 | alter table piston_runs modify user_id varchar(32) not null; 9 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210314201643-challenge-draft.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table challenges add draft tinyint unsigned not null default 1 after challenge_id; 3 | update challenges set draft = 0; 4 | 5 | down: 6 | alter table challenges drop column draft; 7 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210319145442-add-disallowed-languages.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table contests add disallowed_languages varchar(2048) after output; 3 | update contests set disallowed_languages = 'python2,awk'; 4 | 5 | down: 6 | alter table contests drop column disallowed_languages; 7 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210325110214-change-character-set.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table awards convert to character set utf8mb4; 3 | alter table challenge_tests convert to character set utf8mb4; 4 | alter table challenges convert to character set utf8mb4; 5 | alter table cli_scripts convert to character set utf8mb4; 6 | alter table contest_submissions convert to character set utf8mb4; 7 | alter table contests convert to character set utf8mb4; 8 | alter table discord_chat_messages convert to character set utf8mb4; 9 | alter table piston_runs convert to character set utf8mb4; 10 | alter table rmig convert to character set utf8mb4; 11 | alter table snippets convert to character set utf8mb4; 12 | alter table sticker_orders convert to character set utf8mb4; 13 | alter table tags convert to character set utf8mb4; 14 | alter table user_challenges convert to character set utf8mb4; 15 | alter table users convert to character set utf8mb4; 16 | 17 | down: 18 | alter table awards convert to character set utf8; 19 | alter table challenge_tests convert to character set utf8; 20 | alter table challenges convert to character set utf8; 21 | alter table cli_scripts convert to character set utf8; 22 | alter table contest_submissions convert to character set utf8; 23 | alter table contests convert to character set utf8; 24 | alter table discord_chat_messages convert to character set utf8; 25 | alter table piston_runs convert to character set utf8; 26 | alter table rmig convert to character set utf8; 27 | alter table snippets convert to character set utf8; 28 | alter table sticker_orders convert to character set utf8; 29 | alter table tags convert to character set utf8; 30 | alter table user_challenges convert to character set utf8; 31 | alter table users convert to character set utf8; 32 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210326154806-add-late-submissions.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table contest_submissions add late tinyint unsigned default 0; 3 | 4 | down: 5 | alter table contest_submissions drop column late; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210401114642-add-explanation-field.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table contest_submissions add explanation mediumtext not null after length; 3 | 4 | down: 5 | alter table contest_submissions drop column explanation; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210423100104-add-language-version.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table contest_submissions add language_version varchar(32) not null after length; 3 | 4 | down: 5 | alter table contest_submissions drop column language_version; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210714100104-add-best-length.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table contest_submissions add length_best int unsigned not null after length; 3 | 4 | down: 5 | alter table contest_submissions drop column length_best; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20210901095201-remove-contest-draft-field.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table contests drop column draft; 3 | 4 | down: 5 | alter table contests add draft tinyint unsigned not null default 1 after contest_id; 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20220706141314-drop-challenges-folder.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table challenges drop column folder; 3 | 4 | down: 5 | alter table challenges add column folder varchar(64) not null 6 | -------------------------------------------------------------------------------- /platform/migrations/migrations/20220707092911-drop-official-field.sql: -------------------------------------------------------------------------------- 1 | up: 2 | alter table challenge_tests drop column official; 3 | 4 | down: 5 | alter table challenge_tests add column official tinyint(1) default null; 6 | 7 | -------------------------------------------------------------------------------- /platform/models/awards.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class awards extends Sequelize.Model {} 5 | 6 | awards.init( 7 | { 8 | award_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | type: DataTypes.INTEGER, 14 | points: DataTypes.INTEGER, 15 | user_id: DataTypes.INTEGER, 16 | ref_type: DataTypes.INTEGER, 17 | ref_id: DataTypes.INTEGER, 18 | created_at: DataTypes.DATE, 19 | 20 | // getters 21 | tooltip_text: { 22 | type: DataTypes.VIRTUAL, 23 | get() { 24 | return ( 25 | { 26 | [constant.awards.type.contest_first_overall]: 27 | 'Placed 1st overall in a contest', 28 | [constant.awards.type.contest_second_overall]: 29 | 'Placed 2nd overall in a contest', 30 | [constant.awards.type.contest_third_overall]: 31 | 'Placed 3rd overall in a contest', 32 | [constant.awards.type.contest_first_language]: 33 | 'Placed 1st for a specific language in a contest', 34 | [constant.awards.type.general_participation]: 35 | 'Participation' 36 | }[this.type] || '' 37 | ); 38 | } 39 | } 40 | }, 41 | { 42 | sequelize, 43 | modelName: 'awards', 44 | freezeTableName: true, 45 | hooks: { 46 | beforeCreate(instance) { 47 | instance.created_at = util.now(); 48 | } 49 | } 50 | } 51 | ); 52 | 53 | return awards; 54 | }; 55 | -------------------------------------------------------------------------------- /platform/models/challenge_tests.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class challenge_tests extends Sequelize.Model {} 5 | 6 | challenge_tests.init( 7 | { 8 | challenge_test_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | challenge_id: DataTypes.INTEGER, 14 | name: DataTypes.STRING, 15 | input: DataTypes.TEXT, 16 | output: DataTypes.TEXT 17 | }, 18 | { 19 | sequelize, 20 | modelName: 'challenge_tests', 21 | freezeTableName: true 22 | } 23 | ); 24 | 25 | return challenge_tests; 26 | }; 27 | -------------------------------------------------------------------------------- /platform/models/challenges.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class challenges extends Sequelize.Model {} 5 | 6 | challenges.init( 7 | { 8 | challenge_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | draft: DataTypes.INTEGER, 14 | difficulty: DataTypes.INTEGER, 15 | points: DataTypes.INTEGER, 16 | name: DataTypes.STRING, 17 | description: DataTypes.STRING, 18 | html: DataTypes.TEXT('medium'), 19 | 20 | // getters 21 | difficulty_name: { 22 | type: DataTypes.VIRTUAL, 23 | get() { 24 | return ( 25 | { 26 | [constant.challenges.difficulty.easy]: 'easy', 27 | [constant.challenges.difficulty.medium]: 'medium', 28 | [constant.challenges.difficulty.hard]: 'hard' 29 | }[this.difficulty] || null 30 | ); 31 | } 32 | }, 33 | difficulty_name_upper: { 34 | type: DataTypes.VIRTUAL, 35 | get() { 36 | return ( 37 | { 38 | [constant.challenges.difficulty.easy]: 'Easy', 39 | [constant.challenges.difficulty.medium]: 'Medium', 40 | [constant.challenges.difficulty.hard]: 'Hard' 41 | }[this.difficulty] || null 42 | ); 43 | } 44 | } 45 | }, 46 | { 47 | sequelize, 48 | modelName: 'challenges', 49 | freezeTableName: true, 50 | hooks: {} 51 | } 52 | ); 53 | 54 | return challenges; 55 | }; 56 | -------------------------------------------------------------------------------- /platform/models/cli_scripts.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class cli_scripts extends Sequelize.Model {} 5 | 6 | cli_scripts.init( 7 | { 8 | cli_script_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | user_id: DataTypes.INTEGER, 14 | is_public: DataTypes.INTEGER, 15 | is_safe: DataTypes.INTEGER, 16 | title: DataTypes.STRING, 17 | content: DataTypes.TEXT('medium'), 18 | created_at: DataTypes.DATE, 19 | 20 | // getters 21 | view_url: { 22 | type: DataTypes.VIRTUAL, 23 | get() { 24 | return ( 25 | '/scripts/' + 26 | this.cli_script_id + 27 | '/' + 28 | util.slugify(this.title) 29 | ); 30 | } 31 | }, 32 | exec_url: { 33 | type: DataTypes.VIRTUAL, 34 | get() { 35 | return '/exec/' + this.cli_script_id; 36 | } 37 | } 38 | }, 39 | { 40 | sequelize, 41 | modelName: 'cli_scripts', 42 | freezeTableName: true, 43 | hooks: { 44 | beforeCreate(instance) { 45 | instance.created_at = util.now(); 46 | } 47 | } 48 | } 49 | ); 50 | 51 | return cli_scripts; 52 | }; 53 | -------------------------------------------------------------------------------- /platform/models/contest_submissions.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class contest_submissions extends Sequelize.Model {} 5 | 6 | contest_submissions.init( 7 | { 8 | contest_submission_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | user_id: DataTypes.INTEGER, 14 | contest_id: DataTypes.INTEGER, 15 | language: DataTypes.STRING, 16 | language_version: DataTypes.STRING, 17 | solution: DataTypes.TEXT('medium'), 18 | length: DataTypes.INTEGER, 19 | length_best: DataTypes.INTEGER, 20 | explanation: DataTypes.TEXT('medium'), 21 | award_place: DataTypes.INTEGER, 22 | award_points: DataTypes.INTEGER, 23 | created_at: DataTypes.DATE, 24 | late: DataTypes.INTEGER 25 | }, 26 | { 27 | sequelize, 28 | modelName: 'contest_submissions', 29 | freezeTableName: true, 30 | hooks: { 31 | beforeCreate(instance) { 32 | instance.created_at = util.now(); 33 | } 34 | } 35 | } 36 | ); 37 | 38 | return contest_submissions; 39 | }; 40 | -------------------------------------------------------------------------------- /platform/models/discord_chat_messages.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class discord_chat_messages extends Sequelize.Model {} 5 | 6 | discord_chat_messages.init( 7 | { 8 | discord_chat_message_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | hash: DataTypes.STRING, 14 | channel: DataTypes.STRING, 15 | user: DataTypes.STRING, 16 | discord_id: DataTypes.STRING, 17 | message: DataTypes.STRING, 18 | created_at: DataTypes.DATE 19 | }, 20 | { 21 | sequelize, 22 | modelName: 'discord_chat_messages', 23 | freezeTableName: true, 24 | hooks: { 25 | beforeCreate(instance) { 26 | instance.created_at = util.now(); 27 | } 28 | } 29 | } 30 | ); 31 | 32 | return discord_chat_messages; 33 | }; 34 | -------------------------------------------------------------------------------- /platform/models/piston_runs.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class piston_runs extends Sequelize.Model {} 5 | 6 | piston_runs.init( 7 | { 8 | piston_run_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | server: DataTypes.STRING, 14 | server_id: DataTypes.STRING, 15 | user: DataTypes.STRING, 16 | user_id: DataTypes.STRING, 17 | language: DataTypes.STRING, 18 | source: DataTypes.TEXT, 19 | created_at: DataTypes.DATE 20 | }, 21 | { 22 | sequelize, 23 | modelName: 'piston_runs', 24 | freezeTableName: true, 25 | hooks: { 26 | beforeCreate(instance) { 27 | instance.created_at = util.now(); 28 | } 29 | } 30 | } 31 | ); 32 | 33 | return piston_runs; 34 | }; 35 | -------------------------------------------------------------------------------- /platform/models/sticker_orders.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class sticker_orders extends Sequelize.Model {} 5 | 6 | sticker_orders.init( 7 | { 8 | sticker_order_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | is_fulfilled: DataTypes.INTEGER, 14 | tx: DataTypes.STRING, 15 | coupon: DataTypes.STRING, 16 | quantity: DataTypes.INTEGER, 17 | cost: DataTypes.DECIMAL(5, 2), 18 | name: DataTypes.STRING, 19 | email: DataTypes.STRING, 20 | address: DataTypes.TEXT, 21 | created_at: DataTypes.DATE 22 | }, 23 | { 24 | sequelize, 25 | modelName: 'sticker_orders', 26 | freezeTableName: true, 27 | hooks: { 28 | beforeCreate(instance) { 29 | instance.created_at = util.now(); 30 | } 31 | } 32 | } 33 | ); 34 | 35 | return sticker_orders; 36 | }; 37 | -------------------------------------------------------------------------------- /platform/models/tags.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class tags extends Sequelize.Model {} 5 | 6 | tags.init( 7 | { 8 | tag_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | name: DataTypes.STRING 14 | }, 15 | { 16 | sequelize, 17 | modelName: 'tags', 18 | freezeTableName: true, 19 | hooks: {} 20 | } 21 | ); 22 | 23 | return tags; 24 | }; 25 | -------------------------------------------------------------------------------- /platform/models/user_challenges.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | 3 | module.exports = (sequelize, DataTypes) => { 4 | class user_challenges extends Sequelize.Model {} 5 | 6 | user_challenges.init( 7 | { 8 | user_challenge_id: { 9 | type: DataTypes.INTEGER, 10 | primaryKey: true, 11 | autoIncrement: true 12 | }, 13 | user_id: DataTypes.INTEGER, 14 | challenge_id: DataTypes.INTEGER, 15 | language: DataTypes.STRING, 16 | solution: DataTypes.TEXT('medium'), 17 | created_at: DataTypes.DATE 18 | }, 19 | { 20 | sequelize, 21 | modelName: 'user_challenges', 22 | freezeTableName: true, 23 | hooks: { 24 | beforeCreate(instance) { 25 | instance.created_at = util.now(); 26 | } 27 | } 28 | } 29 | ); 30 | 31 | return user_challenges; 32 | }; 33 | -------------------------------------------------------------------------------- /platform/models/users.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | const crypto = require('crypto'); 3 | 4 | module.exports = (sequelize, DataTypes) => { 5 | class users extends Sequelize.Model {} 6 | 7 | users.init( 8 | { 9 | user_id: { 10 | type: DataTypes.INTEGER, 11 | primaryKey: true, 12 | autoIncrement: true 13 | }, 14 | is_staff: DataTypes.INTEGER, 15 | display_name: DataTypes.STRING, 16 | username: DataTypes.STRING, 17 | email: DataTypes.STRING, 18 | password: DataTypes.STRING, 19 | discord_api: DataTypes.STRING, 20 | discord_rank: DataTypes.INTEGER, 21 | avatar_url: DataTypes.STRING, 22 | score: DataTypes.INTEGER, 23 | created_at: DataTypes.DATE 24 | }, 25 | { 26 | sequelize, 27 | modelName: 'users', 28 | freezeTableName: true, 29 | hooks: { 30 | beforeCreate(instance) { 31 | instance.created_at = util.now(); 32 | 33 | if (instance.password) 34 | instance.password = crypto 35 | .createHash('sha1') 36 | .update(instance.password) 37 | .digest('hex'); 38 | }, 39 | 40 | beforeUpdate(instance) { 41 | if (instance.changed('password')) 42 | instance.password = crypto 43 | .createHash('sha1') 44 | .update(instance.password) 45 | .digest('hex'); 46 | } 47 | } 48 | } 49 | ); 50 | 51 | return users; 52 | }; 53 | -------------------------------------------------------------------------------- /platform/pm2.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "emkc", 3 | "args": ["-i 0"], 4 | "script": "emkc.js", 5 | "node_args": ["--max_old_space_size=4096"], 6 | "error_file": "/var/log/emkc.log", 7 | "out_file": "/var/log/emkc.log", 8 | "instances": 0, 9 | "merge_logs": true, 10 | "log_date_format": "YYYY-MM-DD HH:mm Z", 11 | "exec_mode": "cluster" 12 | } 13 | -------------------------------------------------------------------------------- /platform/public/cdn: -------------------------------------------------------------------------------- 1 | ../../cdn/ -------------------------------------------------------------------------------- /platform/public/css/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/css/.gitkeep -------------------------------------------------------------------------------- /platform/public/images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/404.png -------------------------------------------------------------------------------- /platform/public/images/502_animated.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/502_animated.gif -------------------------------------------------------------------------------- /platform/public/images/awards/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/awards/1.png -------------------------------------------------------------------------------- /platform/public/images/awards/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/awards/2.png -------------------------------------------------------------------------------- /platform/public/images/awards/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/awards/3.png -------------------------------------------------------------------------------- /platform/public/images/awards/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/awards/4.png -------------------------------------------------------------------------------- /platform/public/images/awards/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/awards/5.png -------------------------------------------------------------------------------- /platform/public/images/icon_circle_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/icon_circle_24.png -------------------------------------------------------------------------------- /platform/public/images/icon_circle_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/icon_circle_64.png -------------------------------------------------------------------------------- /platform/public/images/icon_square_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/icon_square_64.png -------------------------------------------------------------------------------- /platform/public/images/lang_icons/easy/c.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/easy/cpp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/easy/cs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/easy/go.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/easy/js.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/easy/ruby.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/easy/swift.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/hard/c.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/hard/cpp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/hard/cs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/hard/go.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/hard/js.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/hard/ruby.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/hard/swift.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/medium/c.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/medium/cpp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/medium/cs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/medium/go.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/medium/js.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/medium/ruby.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/lang_icons/medium/swift.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/public/images/sticker_2019.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/images/sticker_2019.png -------------------------------------------------------------------------------- /platform/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/js/.gitkeep -------------------------------------------------------------------------------- /platform/public/lib/highlightjs/atom-one-dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Atom One Dark by Daniel Gamage 4 | Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax 5 | 6 | base: #282c34 7 | mono-1: #abb2bf 8 | mono-2: #818896 9 | mono-3: #5c6370 10 | hue-1: #56b6c2 11 | hue-2: #61aeee 12 | hue-3: #c678dd 13 | hue-4: #98c379 14 | hue-5: #e06c75 15 | hue-5-2: #be5046 16 | hue-6: #d19a66 17 | hue-6-2: #e6c07b 18 | 19 | */ 20 | 21 | .hljs { 22 | display: block; 23 | overflow-x: auto; 24 | padding: 0.5em; 25 | color: #abb2bf; 26 | background: #24282F !important; 27 | } 28 | 29 | .hljs-comment, 30 | .hljs-quote { 31 | color: #5c6370; 32 | font-style: italic; 33 | } 34 | 35 | .hljs-doctag, 36 | .hljs-keyword, 37 | .hljs-formula { 38 | color: #c678dd; 39 | } 40 | 41 | .hljs-section, 42 | .hljs-name, 43 | .hljs-selector-tag, 44 | .hljs-deletion, 45 | .hljs-subst { 46 | color: #e06c75; 47 | } 48 | 49 | .hljs-literal { 50 | color: #56b6c2; 51 | } 52 | 53 | .hljs-string, 54 | .hljs-regexp, 55 | .hljs-addition, 56 | .hljs-attribute, 57 | .hljs-meta-string { 58 | color: #98c379; 59 | } 60 | 61 | .hljs-built_in, 62 | .hljs-class .hljs-title { 63 | color: #e6c07b; 64 | } 65 | 66 | .hljs-attr, 67 | .hljs-variable, 68 | .hljs-template-variable, 69 | .hljs-type, 70 | .hljs-selector-class, 71 | .hljs-selector-attr, 72 | .hljs-selector-pseudo, 73 | .hljs-number { 74 | color: #d19a66; 75 | } 76 | 77 | .hljs-symbol, 78 | .hljs-bullet, 79 | .hljs-link, 80 | .hljs-meta, 81 | .hljs-selector-id, 82 | .hljs-title { 83 | color: #61aeee; 84 | } 85 | 86 | .hljs-emphasis { 87 | font-style: italic; 88 | } 89 | 90 | .hljs-strong { 91 | font-weight: bold; 92 | } 93 | 94 | .hljs-link { 95 | text-decoration: underline; 96 | } 97 | -------------------------------------------------------------------------------- /platform/public/lib/highlightjs/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Original highlight.js style (c) Ivan Sagalaev 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: #F0F0F0; 12 | } 13 | 14 | 15 | /* Base color: saturation 0; */ 16 | 17 | .hljs, 18 | .hljs-subst { 19 | color: #444; 20 | } 21 | 22 | .hljs-comment { 23 | color: #888888; 24 | } 25 | 26 | .hljs-keyword, 27 | .hljs-attribute, 28 | .hljs-selector-tag, 29 | .hljs-meta-keyword, 30 | .hljs-doctag, 31 | .hljs-name { 32 | font-weight: bold; 33 | } 34 | 35 | 36 | /* User color: hue: 0 */ 37 | 38 | .hljs-type, 39 | .hljs-string, 40 | .hljs-number, 41 | .hljs-selector-id, 42 | .hljs-selector-class, 43 | .hljs-quote, 44 | .hljs-template-tag, 45 | .hljs-deletion { 46 | color: #880000; 47 | } 48 | 49 | .hljs-title, 50 | .hljs-section { 51 | color: #880000; 52 | font-weight: bold; 53 | } 54 | 55 | .hljs-regexp, 56 | .hljs-symbol, 57 | .hljs-variable, 58 | .hljs-template-variable, 59 | .hljs-link, 60 | .hljs-selector-attr, 61 | .hljs-selector-pseudo { 62 | color: #BC6060; 63 | } 64 | 65 | 66 | /* Language color: hue: 90; */ 67 | 68 | .hljs-literal { 69 | color: #78A960; 70 | } 71 | 72 | .hljs-built_in, 73 | .hljs-bullet, 74 | .hljs-code, 75 | .hljs-addition { 76 | color: #397300; 77 | } 78 | 79 | 80 | /* Meta color: hue: 200 */ 81 | 82 | .hljs-meta { 83 | color: #1f7199; 84 | } 85 | 86 | .hljs-meta-string { 87 | color: #4d99bf; 88 | } 89 | 90 | 91 | /* Misc effects */ 92 | 93 | .hljs-emphasis { 94 | font-style: italic; 95 | } 96 | 97 | .hljs-strong { 98 | font-weight: bold; 99 | } 100 | -------------------------------------------------------------------------------- /platform/public/lib/highlightjs/highlight-ln.js: -------------------------------------------------------------------------------- 1 | !function(n,e){"use strict";function t(){var n=e.createElement("style");n.type="text/css",n.innerHTML=h(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[f,m,j]),e.getElementsByTagName("head")[0].appendChild(n)}function r(t){"complete"===e.readyState?l(t):n.addEventListener("DOMContentLoaded",function(){l(t)})}function l(t){try{var r=e.querySelectorAll("code.hljs");for(var l in r)r.hasOwnProperty(l)&&i(r[l],t)}catch(o){n.console.error("LineNumbers error: ",o)}}function i(n,e){if("object"==typeof n){e=e||{singleLine:!1};var t=e.singleLine?0:1;u(function(){s(n),n.innerHTML=o(n.innerHTML,t)})}}function o(n,e){var t=c(n);if(""===t[t.length-1].trim()&&t.pop(),t.length>e){for(var r="",l=0,i=t.length;l
{6}
',[v,g,m,j,p,l+1,t[l].length>0?t[l]:" "]);return h('{1}
',[f,r])}return n}function s(n){var e=n.childNodes;for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];d(r.textContent)>0&&(r.childNodes.length>0?s(r):a(r.parentNode))}}function a(n){var e=n.className;if(/hljs-/.test(e)){for(var t=c(n.innerHTML),r=0,l="";r{1}\n',[e,t[r]]);n.innerHTML=l.trim()}}function c(n){return 0===n.length?[]:n.split(L)}function d(n){return(n.trim().match(L)||[]).length}function u(e){n.setTimeout(e,0)}function h(n,e){return n.replace(/\{(\d+)\}/g,function(n,t){return e[t]?e[t]:n})}var f="hljs-ln",g="hljs-ln-line",p="hljs-ln-code",v="hljs-ln-numbers",m="hljs-ln-n",j="data-line-number",L=/\r\n|\r|\n/g;n.hljs?(n.hljs.initLineNumbersOnLoad=r,n.hljs.lineNumbersBlock=i,t()):n.console.error("highlight.js not detected!")}(window,document); 2 | -------------------------------------------------------------------------------- /platform/public/lib/webpack/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/lib/webpack/.gitkeep -------------------------------------------------------------------------------- /platform/public/other/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/public/other/.gitkeep -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) { 6 | %%_INSERTVALUES_%% 7 | 8 | // write your solution here 9 | } 10 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | %%_INSERTVALUES_%% 6 | 7 | // write your solution here 8 | } 9 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | class MainClass { 4 | static void Main(string[] args) { 5 | %%_INSERTVALUES_%% 6 | 7 | // write your solution here 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | %%_IMPORTS_%% 7 | ) 8 | 9 | func main() { 10 | %%_INSERTVALUES_%% 11 | 12 | // write your solution here 13 | } 14 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.hs: -------------------------------------------------------------------------------- 1 | import System.Environment 2 | 3 | main = do 4 | args <- getArgs 5 | %%_INSERTVALUES_%% 6 | -- write your solution here 7 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | public static void main(String[] args) { 3 | %%_INSERTVALUES_%% 4 | 5 | // write your solution here 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.jl: -------------------------------------------------------------------------------- 1 | %%_INSERTVALUES_%% 2 | 3 | # write your solution here 4 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.js: -------------------------------------------------------------------------------- 1 | %%_INSERTVALUES_%% 2 | 3 | // write your solution here 4 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.kt: -------------------------------------------------------------------------------- 1 | fun main(args: Array) { 2 | %%_INSERTVALUES_%% 3 | 4 | // write your solution here 5 | } 6 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.nim: -------------------------------------------------------------------------------- 1 | %%_INSERTVALUES_%% 2 | 3 | # write your solution here 4 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.php: -------------------------------------------------------------------------------- 1 | = env::args().collect(); 7 | 8 | %%_INSERTVALUES_%% 9 | 10 | // write your solution here 11 | } 12 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.sh: -------------------------------------------------------------------------------- 1 | %%_INSERTVALUES_%% 2 | 3 | # write your solution here 4 | -------------------------------------------------------------------------------- /platform/resources/challenges/templates/template.swift: -------------------------------------------------------------------------------- 1 | %%_INSERTVALUES_%% 2 | 3 | // write your solution here 4 | -------------------------------------------------------------------------------- /platform/resources/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/platform/resources/js/.gitkeep -------------------------------------------------------------------------------- /platform/resources/js/challenges/get_language_version.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | $(document).ready(async function () { 4 | if ($('.get-versions').length > 0) { 5 | var languages = await axios.get('/api/v1/piston/versions'); 6 | $('.version').each(function () { 7 | let language = languages.data.filter( 8 | (lang) => $(this).data('langname') === lang.name 9 | )[0]; 10 | $(this).append(language.version); 11 | }); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /platform/resources/js/common.js: -------------------------------------------------------------------------------- 1 | const Constants = { 2 | exp_mo: [ 3 | '01', 4 | '02', 5 | '03', 6 | '04', 7 | '05', 8 | '06', 9 | '07', 10 | '08', 11 | '09', 12 | '10', 13 | '11', 14 | '12' 15 | ], 16 | 17 | exp_yr: new Array(10).fill(new Date().getFullYear()).map((n, i) => n + i) 18 | }; 19 | 20 | export default Constants; 21 | -------------------------------------------------------------------------------- /platform/resources/js/snippets/delete_snippet.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | $(document).on('click', '.confirm-delete', function (e) { 4 | var hash = $(this).data('hash'); 5 | 6 | bootbox.confirm({ 7 | message: 'Are you sure you want to delete this snippet?', 8 | buttons: { 9 | confirm: { 10 | label: 'Delete', 11 | className: 'btn-danger' 12 | }, 13 | cancel: { 14 | label: 'Cancel', 15 | className: 'btn-secondary' 16 | } 17 | }, 18 | callback: async function (result) { 19 | if (result) { 20 | let res = await axios.post('/snippets/delete/' + hash); 21 | location = res.data.url; 22 | } 23 | } 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /platform/resources/js/util.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | class Util { 5 | static unpack_props(props) { 6 | for (const key in props) { 7 | try { 8 | props[key] = JSON.parse(props[key]); 9 | } catch (e) {} 10 | } 11 | } 12 | 13 | static try_render(id, comp) { 14 | if (document.getElementById(id)) { 15 | let ele = document.getElementById(id); 16 | 17 | const final = {}; 18 | 19 | for (const key in ele.dataset) { 20 | try { 21 | final[key] = JSON.parse(ele.dataset[key]); 22 | } catch (e) {} 23 | } 24 | 25 | return ReactDOM.render( 26 | React.createElement(comp, final), 27 | document.getElementById(id) 28 | ); 29 | } 30 | } 31 | 32 | static are_test_cases_valid(test_object) { 33 | return ( 34 | test_object.input !== '' && 35 | test_object.output !== '' && 36 | test_object.input.split('\n').length === 37 | test_object.output.split('\n').length 38 | ); 39 | } 40 | } 41 | 42 | export default Util; 43 | -------------------------------------------------------------------------------- /platform/resources/jsx/cli_script.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Util from 'js/util'; 4 | 5 | class CliScript extends React.Component { 6 | componentDidMount() { 7 | let editor = monaco.editor.create(document.getElementById('editor'), { 8 | theme: 'em', 9 | value: this.props.content, 10 | language: 'shell', 11 | automaticLayout: true, 12 | fontSize: 16, 13 | readOnly: true, 14 | wordWrap: 'off', 15 | scrollBeyondLastLine: false, 16 | scrollbar: { 17 | vertical: 'hidden' 18 | }, 19 | minimap: { 20 | enabled: false 21 | } 22 | }); 23 | 24 | document.getElementById('editor').style.height = 25 | editor.getModel().getLineCount() * 22 + 'px'; 26 | } 27 | 28 | render() { 29 | return
; 30 | } 31 | } 32 | 33 | Util.try_render('react_cli_script', CliScript); 34 | 35 | export default CliScript; 36 | -------------------------------------------------------------------------------- /platform/resources/jsx/contests/description.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Quill from 'quill'; 3 | 4 | class Description extends React.PureComponent { 5 | ops_to_html(ops) { 6 | try { 7 | ops = JSON.parse(ops).ops; 8 | var tmp = document.createElement('div'); 9 | new Quill(tmp, { modules: { syntax: true } }).setContents(ops); 10 | return tmp.getElementsByClassName('ql-editor')[0].innerHTML; 11 | } catch (e) { 12 | return ''; 13 | } 14 | } 15 | 16 | render() { 17 | return ( 18 |
19 |
25 |
26 | ); 27 | } 28 | } 29 | 30 | export default Description; 31 | -------------------------------------------------------------------------------- /platform/resources/jsx/login.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Util from 'js/util'; 4 | 5 | class Login extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { 10 | open: false 11 | }; 12 | 13 | this.open = this.open.bind(this); 14 | this.close = this.close.bind(this); 15 | } 16 | 17 | open(redirect) { 18 | this.setState({ 19 | open: true, 20 | redirect: redirect || location.pathname 21 | }); 22 | } 23 | 24 | close() { 25 | this.setState({ 26 | open: false 27 | }); 28 | } 29 | 30 | render() { 31 | return ( 32 | 54 | ); 55 | } 56 | } 57 | 58 | window.login = Util.try_render('react_login', Login); 59 | 60 | export default Login; 61 | -------------------------------------------------------------------------------- /platform/resources/less/bootstrap.less: -------------------------------------------------------------------------------- 1 | .btn-success { 2 | background-color: #37b86e; 3 | &:hover { 4 | background-color: #289254; 5 | } 6 | } 7 | 8 | .badge-success { 9 | background-color: #37b86e; 10 | } 11 | 12 | .dropdown-menu { 13 | a:visited, 14 | a:link, 15 | a:hover { 16 | color: #333 !important; 17 | } 18 | a:active { 19 | color: #fff !important; 20 | } 21 | .dropdown-item { 22 | &:active { 23 | background-color: #36b96e; 24 | } 25 | } 26 | } 27 | 28 | .bootbox-body { 29 | text-align: left; 30 | color: #000; 31 | } 32 | 33 | .highlightjs * { 34 | font-size: 14px !important; 35 | font-family: monospace !important; 36 | } 37 | 38 | select { 39 | background: none !important; 40 | outline: none !important; 41 | border: #999 1px solid !important; 42 | background: #282c34 !important; 43 | color: #fff !important; 44 | } 45 | 46 | input.form-control, 47 | textarea.form-control { 48 | background: none !important; 49 | border: 0 !important; 50 | border-bottom: #666 1px solid !important; 51 | padding-left: 0 !important; 52 | outline: 0 !important; 53 | color: #fff !important; 54 | &:focus { 55 | box-shadow: none !important; 56 | outline: 0 !important; 57 | } 58 | } 59 | 60 | .form-box { 61 | padding: 15px; 62 | background: #21252b; 63 | margin: 30px 0; 64 | } 65 | 66 | hr { 67 | border-top: #000 1px solid; 68 | } 69 | 70 | .btn { 71 | &:focus { 72 | box-shadow: none; 73 | } 74 | } 75 | 76 | table { 77 | th { 78 | border-top: 0 !important; 79 | } 80 | } 81 | 82 | .text-warning { 83 | color: #ffdd78 !important; 84 | } 85 | -------------------------------------------------------------------------------- /platform/resources/less/colors.less: -------------------------------------------------------------------------------- 1 | @challenge_easy: #84e47f; 2 | @challenge_medium: #e4e37f; 3 | @challenge_hard: #e47f8d; 4 | 5 | .green { 6 | color: #8aecb4; 7 | } 8 | -------------------------------------------------------------------------------- /platform/resources/less/em/challenge.less: -------------------------------------------------------------------------------- 1 | @import '../colors.less'; 2 | 3 | .em_challenge { 4 | position: absolute; 5 | top: 56px; 6 | left: 0; 7 | right: 0; 8 | bottom: 0; 9 | display: flex; 10 | 11 | pre { 12 | font: inherit; 13 | color: inherit; 14 | display: inline; 15 | } 16 | 17 | .instructions { 18 | width: 360px; 19 | overflow-y: auto; 20 | padding: 15px; 21 | } 22 | 23 | .editor { 24 | flex: 1; 25 | position: relative; 26 | } 27 | 28 | #editor { 29 | position: absolute; 30 | top: 0; 31 | left: 0; 32 | right: 0; 33 | bottom: 0; 34 | } 35 | 36 | .easy { 37 | color: @challenge_easy; 38 | } 39 | 40 | .medium { 41 | color: @challenge_medium; 42 | } 43 | 44 | .hard { 45 | color: @challenge_hard; 46 | } 47 | 48 | .results { 49 | position: fixed; 50 | top: 70%; 51 | bottom: 0; 52 | left: 454px; 53 | right: 30px; 54 | background: rgba(0, 0, 0, 0.3); 55 | padding: 25px; 56 | overflow: auto; 57 | .result { 58 | background: rgba(0, 0, 0, 0.2); 59 | padding: 10px 15px; 60 | margin-bottom: 10px; 61 | color: #fff; 62 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, 63 | 'Liberation Mono', 'Courier New', monospace; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /platform/resources/less/em/challenge_abstract.less: -------------------------------------------------------------------------------- 1 | .em_challenge .abstract, 2 | #react_manage_challenge .ql-editor { 3 | .input { 4 | p:last-child { 5 | margin-bottom: 0; 6 | } 7 | } 8 | .wrap { 9 | word-break: break-all; 10 | } 11 | 12 | .test_case { 13 | background: rgba(0, 0, 0, 0.2); 14 | padding: 10px 15px; 15 | margin-bottom: 10px; 16 | color: #fff; 17 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 18 | 'Courier New', monospace; 19 | > * { 20 | margin-bottom: 5px; 21 | } 22 | } 23 | 24 | p { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | h4 { 30 | font-weight: 300; 31 | } 32 | 33 | .value-badge { 34 | color: #fff; 35 | background-color: #007bff; 36 | display: inline-block; 37 | padding: 0.25em 0.4em; 38 | font-size: 75%; 39 | font-weight: 700; 40 | line-height: 1; 41 | text-align: center; 42 | white-space: nowrap; 43 | vertical-align: baseline; 44 | border-radius: 0.25rem; 45 | transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, 46 | border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; 47 | } 48 | 49 | pre { 50 | display: block; 51 | font-size: 87.5%; 52 | color: #212529; 53 | } 54 | 55 | .section { 56 | margin-bottom: 30px; 57 | } 58 | 59 | .input { 60 | background: rgba(0, 0, 0, 0.2); 61 | padding: 10px 15px; 62 | margin-bottom: 10px; 63 | color: #fff; 64 | } 65 | 66 | .ql-syntax { 67 | background: rgba(0, 0, 0, 0.2); 68 | padding: 10px 15px; 69 | margin-bottom: 20px; 70 | margin-top: -5px; 71 | color: #fff; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /platform/resources/less/em/challenge_manage.less: -------------------------------------------------------------------------------- 1 | .em_challenge_manage { 2 | .case_box { 3 | padding: 15px; 4 | background: #1b1f27; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /platform/resources/less/em/challenges_list.less: -------------------------------------------------------------------------------- 1 | @import '../colors.less'; 2 | 3 | .em_challenges_list { 4 | .challenge_list { 5 | margin-bottom: 20px; 6 | .challenge { 7 | display: block; 8 | background: #21252b; 9 | padding: 10px; 10 | margin-bottom: 8px; 11 | color: #fff; 12 | .title { 13 | font-size: 18px; 14 | } 15 | .description { 16 | font-weight: 300; 17 | } 18 | &:hover { 19 | background: #2f353e; 20 | } 21 | } 22 | } 23 | .easy { 24 | .title { 25 | .badge { 26 | float: right; 27 | } 28 | .text { 29 | color: @challenge_easy; 30 | } 31 | } 32 | } 33 | .medium { 34 | .title { 35 | .badge { 36 | float: right; 37 | } 38 | .text { 39 | color: @challenge_medium; 40 | } 41 | } 42 | } 43 | .hard { 44 | .title { 45 | .badge { 46 | float: right; 47 | } 48 | .text { 49 | color: @challenge_hard; 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /platform/resources/less/em/common_content.less: -------------------------------------------------------------------------------- 1 | .em_common_content { 2 | max-width: 1140px; 3 | width: 100%; 4 | margin-left: auto; 5 | margin-right: auto; 6 | padding: 40px 15px; 7 | h4 { 8 | margin-bottom: 10px; 9 | } 10 | .version { 11 | margin-top: -5px; 12 | } 13 | .col-4 { 14 | margin-top: 5px; 15 | } 16 | } 17 | 18 | .em_wide_content { 19 | padding: 20px 15px; 20 | h4 { 21 | margin-bottom: 10px; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /platform/resources/less/em/community_map.less: -------------------------------------------------------------------------------- 1 | .em_community_map { 2 | max-width: 1100px; 3 | width: 100%; 4 | margin: auto; 5 | padding: 30px 15px; 6 | .link_list { 7 | background: #000; 8 | background: #21252b; 9 | padding: 10px; 10 | margin-bottom: 20px; 11 | a { 12 | display: block; 13 | margin-bottom: 6px; 14 | &:last-child { 15 | margin-bottom: 0; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /platform/resources/less/em/container.less: -------------------------------------------------------------------------------- 1 | .em_container { 2 | display: inline-block; 3 | margin: auto; 4 | /*max-width: 1440px;*/ 5 | width: 100%; 6 | text-align: left; 7 | background: #282c34; 8 | min-height: 100vh; 9 | } 10 | -------------------------------------------------------------------------------- /platform/resources/less/em/contests/contest.less: -------------------------------------------------------------------------------- 1 | .em_contests_contest { 2 | .ql-editor { 3 | padding-left: 0; 4 | padding-right: 0; 5 | } 6 | .header { 7 | margin-bottom: 0; 8 | } 9 | .description { 10 | padding: 30px 0; 11 | } 12 | .case_text { 13 | color: #fff; 14 | background: #24282f; 15 | padding: 8px; 16 | } 17 | .submission { 18 | padding: 10px; 19 | background: rgba(0, 0, 0, 0.1); 20 | margin-bottom: 10px; 21 | .heading { 22 | display: flex; 23 | .main { 24 | flex: 1; 25 | } 26 | .summary { 27 | img { 28 | width: auto; 29 | height: 28px; 30 | margin-left: 6px; 31 | } 32 | } 33 | .user { 34 | padding-top: 8px; 35 | color: #fff; 36 | img { 37 | width: 28px; 38 | height: 28px; 39 | } 40 | } 41 | .time { 42 | font-size: 12px; 43 | color: #aaa; 44 | } 45 | .explanation_text { 46 | font-size: 12px; 47 | } 48 | } 49 | .solution { 50 | margin-left: -8px; 51 | margin-right: -8px; 52 | margin-top: 5px; 53 | padding: 10px; 54 | font-size: 12px; 55 | font-family: monospace; 56 | word-wrap: break-word; 57 | color: #fff; 58 | background: rgba(0, 0, 0, 0.1); 59 | margin-bottom: 0; 60 | white-space: pre-wrap; 61 | } 62 | } 63 | .tab-active { 64 | background-color: #3771b8; 65 | } 66 | .space-between { 67 | display: flex; 68 | justify-content: space-between; 69 | align-items: center; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /platform/resources/less/em/contests/home.less: -------------------------------------------------------------------------------- 1 | .em_contests_home { 2 | * { 3 | color: #fff; 4 | } 5 | .active { 6 | margin-bottom: 40px; 7 | } 8 | .past { 9 | margin-bottom: 40px; 10 | } 11 | .contest { 12 | display: block; 13 | background: rgba(0, 0, 0, 0.3); 14 | padding: 15px; 15 | margin-bottom: 20px; 16 | .name { 17 | font-size: 22px; 18 | margin-bottom: 10px; 19 | } 20 | .time_left { 21 | background: rgba(67, 103, 82, 0.5); 22 | padding: 8px 12px; 23 | margin-bottom: 6px; 24 | } 25 | .solutions { 26 | background: rgb(37, 42, 49); 27 | padding: 8px 12px; 28 | font-size: 20px; 29 | font-weight: 700; 30 | margin-top: 14px; 31 | img { 32 | width: 32px; 33 | height: 32px; 34 | margin-bottom: 4px; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /platform/resources/less/em/contests/manage.less: -------------------------------------------------------------------------------- 1 | .em_contest_manage { 2 | .wrapper { 3 | display: flex; 4 | 5 | .left { 6 | flex: 1; 7 | padding-right: 15px; 8 | } 9 | 10 | .right { 11 | width: 300px; 12 | } 13 | } 14 | 15 | .control_button { 16 | margin-top: 10px; 17 | width: 150px; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /platform/resources/less/em/footer.less: -------------------------------------------------------------------------------- 1 | .em_footer { 2 | position: absolute; 3 | bottom: 0; 4 | left: 0; 5 | right: 0; 6 | background: #36b96e; 7 | font-size: 12px; 8 | padding: 0 10px; 9 | text-align: right; 10 | a { 11 | color: #fff; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /platform/resources/less/em/language_choice.less: -------------------------------------------------------------------------------- 1 | @import '../colors.less'; 2 | 3 | .em_language_choice { 4 | .icons > div { 5 | text-align: center; 6 | margin-bottom: 30px; 7 | } 8 | h4 { 9 | margin: 15px 0; 10 | } 11 | .easy { 12 | color: @challenge_easy; 13 | } 14 | .medium { 15 | color: @challenge_medium; 16 | } 17 | .hard { 18 | color: @challenge_hard; 19 | } 20 | } 21 | 22 | .badge-easy { 23 | background-color: @challenge_easy; 24 | } 25 | .badge-medium { 26 | background-color: @challenge_medium; 27 | } 28 | .badge-hard { 29 | background-color: @challenge_hard; 30 | } 31 | -------------------------------------------------------------------------------- /platform/resources/less/em/login.less: -------------------------------------------------------------------------------- 1 | .em_login { 2 | display: none; 3 | &.open { 4 | display: block; 5 | } 6 | .backdrop { 7 | position: absolute; 8 | top: 0; 9 | left: 0; 10 | bottom: 0; 11 | right: 0; 12 | background: rgba(0, 0, 0, 0.2); 13 | text-align: center; 14 | z-index: 10; 15 | } 16 | .close { 17 | position: absolute; 18 | top: 8px; 19 | right: 8px; 20 | cursor: pointer; 21 | i { 22 | color: #fff; 23 | &:hover { 24 | color: #eee; 25 | } 26 | } 27 | } 28 | .box { 29 | display: inline-block; 30 | position: relative; 31 | max-width: 450px; 32 | width: 100%; 33 | margin-top: 30px; 34 | background: #222; 35 | padding: 30px; 36 | p { 37 | color: #aaa; 38 | margin-top: 20px; 39 | margin-bottom: 25px; 40 | } 41 | a { 42 | color: #fff; 43 | background: #7289da; 44 | &:hover { 45 | background: #687bc0; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /platform/resources/less/em/manage_snippet.less: -------------------------------------------------------------------------------- 1 | .em_manage_snippet { 2 | #editor { 3 | height: calc(100vh - 144px); 4 | @media (max-width: 700px) { 5 | height: calc(100vh - 190px); 6 | } 7 | } 8 | .menu { 9 | .wrapper { 10 | display: flex; 11 | background: #21252b; 12 | align-items: center; 13 | padding: 10px 10px 10px 75px; 14 | @media (max-width: 700px) { 15 | display: grid; 16 | grid-template-columns: 1fr; 17 | align-items: unset; 18 | place-items: center; 19 | gap: 0.5rem; 20 | } 21 | > * { 22 | display: inline-block; 23 | vertical-align: middle; 24 | } 25 | .language { 26 | flex: 1; 27 | select { 28 | width: 200px; 29 | } 30 | } 31 | .language_label { 32 | margin-right: 10px; 33 | flex: 1; 34 | } 35 | .control-button { 36 | margin-right: 0.5rem; 37 | } 38 | } 39 | } 40 | .run-data { 41 | display: flex; 42 | width: 100%; 43 | overflow: auto; 44 | pre { 45 | font: unset; 46 | color: unset; 47 | } 48 | .inputs-outputs { 49 | width: 100%; 50 | padding: 20px 15px; 51 | } 52 | } 53 | .info { 54 | background-color: rgba(0, 0, 0, 0.3); 55 | min-height: 20px; 56 | margin-bottom: 10px; 57 | padding: 10px 5px 5px 5px; 58 | overflow-x: auto; 59 | max-width: 600px; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /platform/resources/less/em/mobile_nav.less: -------------------------------------------------------------------------------- 1 | .em_mobile_nav { 2 | display: none; 3 | &.open { 4 | display: inline; 5 | } 6 | .backdrop { 7 | position: absolute; 8 | top: 0; 9 | left: 0; 10 | bottom: 0; 11 | right: 0; 12 | background: rgba(0, 0, 0, 0.6); 13 | text-align: center; 14 | } 15 | .close { 16 | position: absolute; 17 | top: 8px; 18 | right: 8px; 19 | cursor: pointer; 20 | i { 21 | color: #fff; 22 | &:hover { 23 | color: #eee; 24 | } 25 | } 26 | } 27 | .menu { 28 | position: absolute; 29 | top: 0; 30 | left: 0; 31 | bottom: 0; 32 | width: 75%; 33 | background: #282c34; 34 | color: #fff; 35 | text-align: left; 36 | z-index: 1; 37 | .contents { 38 | padding: 16px; 39 | a { 40 | display: block; 41 | padding: 10px; 42 | background: #22262c; 43 | margin-bottom: 4px; 44 | } 45 | .spacer { 46 | height: 20px; 47 | } 48 | } 49 | } 50 | @media (min-width: 701px) { 51 | display: none !important; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /platform/resources/less/em/power_system.less: -------------------------------------------------------------------------------- 1 | .em_power_system { 2 | .tier_circle { 3 | border-radius: 50%; 4 | width: 100%; 5 | padding-top: 100%; 6 | position: relative; 7 | margin-bottom: 30px; 8 | .wrapper { 9 | position: absolute; 10 | top: ~'calc(50% - 30px)'; 11 | left: 0; 12 | right: 0; 13 | text-align: center; 14 | .tier { 15 | font-size: 26px; 16 | font-weight: 700; 17 | } 18 | .score { 19 | font-size: 26px; 20 | font-weight: 300; 21 | } 22 | } 23 | } 24 | .novice { 25 | background: #79acbf; 26 | } 27 | .hero { 28 | background: #7d9dc5; 29 | } 30 | .master { 31 | background: #acb2e4; 32 | } 33 | .legend { 34 | background: #d2ace4; 35 | } 36 | .power_list { 37 | .item { 38 | display: flex; 39 | background: #21252b; 40 | margin-bottom: 4px; 41 | padding: 6px 12px; 42 | font-size: 18px; 43 | div { 44 | flex: 1; 45 | color: #8fdcef; 46 | } 47 | span { 48 | width: 80px; 49 | padding-left: 30px; 50 | font-weight: 700; 51 | } 52 | } 53 | .heading:first-child { 54 | margin-top: 0; 55 | } 56 | .heading { 57 | margin-top: 30px; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /platform/resources/less/em/profile.less: -------------------------------------------------------------------------------- 1 | @import '../colors.less'; 2 | 3 | .em_profile { 4 | .content { 5 | display: flex; 6 | .left { 7 | width: 220px; 8 | .padding { 9 | padding: 0 10px; 10 | } 11 | } 12 | .right { 13 | flex: 1; 14 | } 15 | } 16 | .avatar { 17 | width: 100%; 18 | height: auto; 19 | margin-bottom: 10px; 20 | } 21 | .awards { 22 | margin-bottom: 30px; 23 | .award { 24 | display: inline-block; 25 | text-align: center; 26 | margin: 5px 10px 10px 10px; 27 | img { 28 | margin-bottom: 5px; 29 | cursor: pointer; 30 | } 31 | } 32 | .count { 33 | background: rgba(0, 0, 0, 0.4); 34 | color: #fff; 35 | text-align: center; 36 | display: inline-block; 37 | border-radius: 20px; 38 | padding: 2px 10px; 39 | } 40 | } 41 | .challenge { 42 | display: block; 43 | background: rgba(0, 0, 0, 0.3); 44 | padding: 10px; 45 | margin-bottom: 10px; 46 | a { 47 | color: #fff; 48 | } 49 | &.easy { 50 | border-left: @challenge_easy 5px solid; 51 | } 52 | &.medium { 53 | border-left: @challenge_medium 5px solid; 54 | } 55 | &.hard { 56 | border-left: @challenge_hard 5px solid; 57 | } 58 | p { 59 | margin-bottom: 8px; 60 | } 61 | } 62 | .view_solution { 63 | width: 80px; 64 | height: 48px; 65 | background: #126536; 66 | padding-right: 10px; 67 | padding-left: 10px; 68 | margin-bottom: 10px; 69 | & p { 70 | margin-bottom: 0; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /platform/resources/less/em/staff_container.less: -------------------------------------------------------------------------------- 1 | .em_staff_container { 2 | padding: 4px 10px; 3 | background: #313847; 4 | } 5 | -------------------------------------------------------------------------------- /platform/resources/less/em/stickers.less: -------------------------------------------------------------------------------- 1 | .em_stickers { 2 | .sticker { 3 | max-width: 200px; 4 | width: 100%; 5 | height: auto; 6 | margin-top: 20px; 7 | margin-bottom: 20px; 8 | } 9 | .quantity_option { 10 | display: inline-block; 11 | padding: 10px 18px; 12 | border: #555 1px solid; 13 | &.active { 14 | background: #208a4d; 15 | } 16 | &:hover { 17 | cursor: pointer; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /platform/resources/less/em/top_members.less: -------------------------------------------------------------------------------- 1 | .em_top_members { 2 | .user_row { 3 | position: relative; 4 | display: flex; 5 | margin-bottom: 4px; 6 | background: #202329; 7 | .score_progress { 8 | position: absolute; 9 | left: 0; 10 | top: 85%; 11 | bottom: 0; 12 | } 13 | .picture { 14 | z-index: 1; 15 | img { 16 | width: 40px; 17 | height: 40px; 18 | } 19 | } 20 | .name { 21 | z-index: 1; 22 | flex: 1; 23 | .wrapper { 24 | display: inline-block; 25 | padding: 2px 8px; 26 | border-radius: 20px; 27 | text-align: center; 28 | margin-top: 6px; 29 | margin-left: 6px; 30 | color: #fff; 31 | } 32 | } 33 | .power { 34 | z-index: 1; 35 | width: 100px; 36 | text-align: right; 37 | .wrapper { 38 | display: inline-block; 39 | padding: 2px 8px; 40 | border-radius: 20px; 41 | text-align: center; 42 | margin-top: 6px; 43 | margin-right: 6px; 44 | color: #fff; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /platform/resources/less/highlightjs.less: -------------------------------------------------------------------------------- 1 | td.hljs-ln-code { 2 | padding-left: 10px !important; 3 | } 4 | td.hljs-ln-numbers { 5 | background: #1b1f27; 6 | padding-left: 5px !important; 7 | padding-right: 15px !important; 8 | } 9 | -------------------------------------------------------------------------------- /platform/resources/less/quill.less: -------------------------------------------------------------------------------- 1 | .ql-toolbar { 2 | background: #1b1f27 !important; 3 | border: 0 !important; 4 | svg { 5 | * { 6 | stroke: #fff !important; 7 | } 8 | } 9 | .ql-strike, 10 | .ql-header { 11 | svg * { 12 | fill: #fff !important; 13 | } 14 | } 15 | .ql-picker-label { 16 | &:hover { 17 | color: #fff !important; 18 | } 19 | } 20 | button { 21 | &:hover { 22 | background: #4aa571 !important; 23 | } 24 | } 25 | } 26 | 27 | .ql-container { 28 | border: 0 !important; 29 | border-bottom: #7b7b7b 1px solid !important; 30 | font-size: 14px !important; 31 | background: #1b1f27 !important; 32 | font-family: Lato, sans-serif; 33 | } 34 | 35 | .ql-blank { 36 | &:before { 37 | color: #ddd !important; 38 | font-style: normal !important; 39 | } 40 | } 41 | 42 | .ql-editor { 43 | font-size: 16px; 44 | min-height: 200px; 45 | .ql-syntax { 46 | margin-top: 10px; 47 | * { 48 | font-family: monospace !important; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /platform/resources/main.js: -------------------------------------------------------------------------------- 1 | import 'core-js/stable'; 2 | import 'regenerator-runtime/runtime'; 3 | 4 | import axios from 'axios'; 5 | 6 | try { 7 | axios.defaults.validateStatus = () => true; 8 | } catch (e) {} 9 | 10 | ((ctx) => { 11 | return ctx.keys().map(ctx); 12 | })(require.context('./js', true, /\.js$/)); 13 | 14 | ((ctx) => { 15 | return ctx.keys().map(ctx); 16 | })(require.context('./jsx', true, /\.jsx$/)); 17 | 18 | ((ctx) => { 19 | return ctx.keys().map(ctx); 20 | })(require.context('./less', true, /\.less$/)); 21 | -------------------------------------------------------------------------------- /platform/resources/monaco.js: -------------------------------------------------------------------------------- 1 | import * as monaco from 'monaco-editor'; 2 | 3 | monaco.editor.defineTheme('em', { 4 | base: 'vs-dark', 5 | inherit: true, 6 | rules: [{ background: '282C34' }], 7 | colors: { 8 | 'editorGutter.background': '#21252B', 9 | 'editor.background': '#282C34', 10 | 'scrollbarSlider.background': '#21252B', 11 | 'scrollbarSlider.hoverBackground': '#21252B', 12 | 'scrollbarSlider.activeBackground': '#21252B' 13 | } 14 | }); 15 | 16 | window.monaco = monaco; 17 | -------------------------------------------------------------------------------- /platform/resources/twig/filters.js: -------------------------------------------------------------------------------- 1 | const contains = (array, value) => { 2 | if (value === undefined || value === null) { 3 | return false; 4 | } 5 | 6 | for (let checking of array) { 7 | let found = true; 8 | 9 | for (let entry of Object.entries(checking)) { 10 | if (value[0][entry[0]] !== entry[1]) { 11 | found = false; 12 | } 13 | } 14 | 15 | if (found) { 16 | return true; 17 | } 18 | } 19 | 20 | return false; 21 | }; 22 | 23 | module.exports = [ 24 | { 25 | name: 'contains', 26 | filter: contains 27 | } 28 | ]; 29 | -------------------------------------------------------------------------------- /platform/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | APPENV=${APPENV:-development} 4 | 5 | echo "running in $APPENV mode" 6 | 7 | if [ $APPENV == "production" ]; then 8 | npm run prod 9 | else 10 | npm run dev 11 | fi 12 | -------------------------------------------------------------------------------- /platform/views/_emails/new_user.twig: -------------------------------------------------------------------------------- 1 | {% extends '_emails/container.twig' %} 2 | {% block content %} 3 | 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /platform/views/admin/challenges/update.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block content %} 3 |
4 |
5 |
6 |
11 |
12 |
13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /platform/views/admin/challenges/view_all.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block content %} 3 |
4 |
5 |
6 |

7 | Challenges 8 | 9 | 10 | 11 | 12 | 13 |

14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {% for challenge in challenges %} 26 | 27 | 35 | 36 | 37 | 38 | 39 | {% endfor %} 40 | 41 |
IDDifficultyName
28 | 29 | 30 | 31 | 32 | 33 | 34 | {{ challenge.challenge_id }}{{ challenge.difficulty_name }}{{ challenge.name }}
42 |
43 |
44 |
45 | {% endblock %} 46 | -------------------------------------------------------------------------------- /platform/views/admin/contests/update.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block content %} 3 |
4 |
5 |
6 |

Manage Contest

7 | 8 |
15 |
16 |
17 |
18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /platform/views/admin/dashboard/dashboard.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block content %} 3 |
4 |
5 |
6 |

Dashboard

7 | Nothing here, choose from above. 8 |
9 |
10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /platform/views/admin/piston/view_all.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block title %}Piston | EMKC{% endblock %} 3 | {% block content %} 4 |
8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /platform/views/admin/users/view_all.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block title %}Users | EMKC{% endblock %} 3 | {% block content %} 4 |
8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /platform/views/challenges/challenge.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block title %}{{ challenge.difficulty_name_upper }} Challenge: {{ challenge.name }} | EMKC{% endblock %} 3 | {% block css %} 4 | {{ parent() }} 5 | 10 | {% endblock %} 11 | {% block bundles %} 12 | 13 | {% endblock %} 14 | {% block content %} 15 |
24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /platform/views/community/about.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block title %}About Engineer Man Knowledge Center{% endblock %} 3 | {% block content %} 4 |
5 |
6 |
7 |

About Engineer Man Knowledge Center

8 | 9 |

10 | The Engineer Man Knowledge Center is a project by Engineer Man 11 | and other collaborators designed 12 | to create a permanent knowledge resource for the people of Discord and the YouTube channel. The platform has drawn 13 | influence from the positive parts of Stack Exchange's Q&A and community systems as well as the discussion 14 | format of Reddit. 15 |

16 | 17 |

18 | The need for a Knowledge Center came about when our Discord server was flooded with people, questions, 19 | resources, ideas, and discussion. It was not practical to continue operating in that way on a service 20 | that was not built for what we were using it for. 21 |

22 |
23 |
24 |
25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /platform/views/contests/contest.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block title %}Coding Contest: {{ contest.name|e }} | EMKC{% endblock %} 3 | {% block content %} 4 |
5 |
6 |
7 |
13 |
14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /platform/views/home/fourohfour.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig' %} 2 | {% block content %} 3 |
4 | 5 |
6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /platform/views/home/login.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block content %} 3 | Discord 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /platform/views/scripts/home.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block content %} 3 |
4 |
5 |
6 |

CLI Script Database

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% for script in scripts %} 18 | 19 | 22 | 23 | 24 | 25 | {% endfor %} 26 | 27 |
ViewTitleCreated
20 | View 21 | {{ script.title }}{{ script.created_at|date('m/d/Y g:i a') }}
28 |
29 |
30 |
31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /platform/views/scripts/view.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig'%} 2 | {% block bundles %} 3 | 4 | {% endblock %} 5 | {% block content %} 6 |
7 |

{{ script.title }}

8 |
bash <(curl -sSf {{ sails.config.base_url }}/exec/{{ script.cli_script_id }})
9 |
14 |
15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /platform/views/snippets/edit.twig: -------------------------------------------------------------------------------- 1 | {% extends 'master.twig' %} 2 | {% block css %} 3 | {{ parent() }} 4 | 12 | {% endblock %} 13 | {% block bundles %} 14 | 15 | {% endblock %} 16 | {% block content %} 17 |
25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /var/502/502.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Engineer Man Knowledge Center 5 | 6 | 7 |
8 | 9 |
10 | Deploying new cool features.
11 | Refresh in a sec. 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /var/artwork/logicons/c#/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c#/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/c#/bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /var/artwork/logicons/c#/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c#/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/c#/nbg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /var/artwork/logicons/c#/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c#/ref.png -------------------------------------------------------------------------------- /var/artwork/logicons/c++/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c++/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/c++/bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /var/artwork/logicons/c++/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c++/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/c++/nbg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /var/artwork/logicons/c++/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c++/ref.png -------------------------------------------------------------------------------- /var/artwork/logicons/c/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/c/bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /var/artwork/logicons/c/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/c/nbg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /var/artwork/logicons/c/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/c/ref.png -------------------------------------------------------------------------------- /var/artwork/logicons/dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/dev.png -------------------------------------------------------------------------------- /var/artwork/logicons/go/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/go/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/go/bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /var/artwork/logicons/go/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/go/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/go/nbg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /var/artwork/logicons/go/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/go/ref.png -------------------------------------------------------------------------------- /var/artwork/logicons/ignore.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/ignore.afdesign -------------------------------------------------------------------------------- /var/artwork/logicons/java/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/java/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/java/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/java/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/java/ref.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/java/ref.jpg -------------------------------------------------------------------------------- /var/artwork/logicons/javascript/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/javascript/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/javascript/bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /var/artwork/logicons/javascript/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/javascript/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/javascript/nbg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /var/artwork/logicons/javascript/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/javascript/ref.png -------------------------------------------------------------------------------- /var/artwork/logicons/php/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/php/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/php/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/php/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/php/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/php/ref.png -------------------------------------------------------------------------------- /var/artwork/logicons/python/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/python/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/python/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/python/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/python/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/python/ref.png -------------------------------------------------------------------------------- /var/artwork/logicons/ruby/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/ruby/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/ruby/bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /var/artwork/logicons/ruby/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/ruby/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/ruby/nbg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /var/artwork/logicons/ruby/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/ruby/ref.png -------------------------------------------------------------------------------- /var/artwork/logicons/swift/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/swift/bg.png -------------------------------------------------------------------------------- /var/artwork/logicons/swift/bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /var/artwork/logicons/swift/nbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/artwork/logicons/swift/nbg.png -------------------------------------------------------------------------------- /var/artwork/logicons/swift/nbg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /var/artwork/logicons/swift/ref.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /var/docker/clean: -------------------------------------------------------------------------------- 1 | rm -rf ./logs/* 2 | rm -rf ./mysql/* 3 | rm -rf ./redis/* 4 | -------------------------------------------------------------------------------- /var/docker/config/mysqld.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | symbolic-links=0 3 | innodb_file_per_table=1 4 | sql_mode = "" 5 | 6 | [server] 7 | #general_log=1 8 | #general_log_file=/opt/emkc/var/docker/logs/sql.log 9 | -------------------------------------------------------------------------------- /var/docker/init/db.sql: -------------------------------------------------------------------------------- 1 | create database if not exists emkc; 2 | -------------------------------------------------------------------------------- /var/docker/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/docker/logs/.gitkeep -------------------------------------------------------------------------------- /var/docker/mysql/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/docker/mysql/.gitkeep -------------------------------------------------------------------------------- /var/docker/redis/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/docker/redis/.gitkeep -------------------------------------------------------------------------------- /var/felix/404felix.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/felix/404felix.psd -------------------------------------------------------------------------------- /var/felix/blue-robot-vector-art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/felix/blue-robot-vector-art.png -------------------------------------------------------------------------------- /var/felix/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/felix/default.png -------------------------------------------------------------------------------- /var/text/a.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/text/a.txt -------------------------------------------------------------------------------- /var/tmp/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/engineer-man/emkc/4b7e6c3baba6d1bf19b643b9a90380e8af8c17fb/var/tmp/.gitkeep -------------------------------------------------------------------------------- /var/tmp/stats.sql: -------------------------------------------------------------------------------- 1 | select 2 | user, 3 | count(*) as messages 4 | from discord_chat_messages 5 | where 6 | created_at > '2021-07-29 00:00:00' and 7 | channel not in ( 8 | 'team-room', 9 | 'hero-room', 10 | 'oof-topic', 11 | 'command-center', 12 | 'moderator-report', 13 | 'gaming', 14 | 'music', 15 | 'bot-playground' 16 | ) and 17 | discord_id in ( 18 | '252862670842232832', 19 | '431464792075665418', 20 | '98488345952256000', 21 | '460172222489952266', 22 | '473160828502409217', 23 | '274618567977205761', 24 | '187677490452496394', 25 | '449274804651032577', 26 | '342099904056786945', 27 | '186436642356068352', 28 | '245697230982479872', 29 | '381632413010231309', 30 | '173679469872152576' 31 | ) 32 | group by discord_id 33 | order by messages desc; 34 | 35 | 36 | select 37 | user, 38 | count(*) as messages 39 | from discord_chat_messages 40 | where 41 | created_at > '2021-07-29 00:00:00' and 42 | channel not in ( 43 | 'team-room', 44 | 'hero-room', 45 | 'oof-topic', 46 | 'command-center', 47 | 'moderator-report', 48 | 'gaming', 49 | 'music', 50 | 'bot-playground' 51 | ) and 52 | discord_id in ( 53 | '319509382889209866', 54 | '681375864042160128', 55 | '222005750598205440', 56 | '243412893234757632', 57 | '532835388448833556', 58 | '271357207180738563', 59 | '406634590325964801', 60 | '276380118761340928', 61 | '563228793704022038', 62 | '496790880548814858', 63 | '158250066417549312', 64 | '266140088138858496', 65 | '710952300209766410', 66 | '197774061315686400', 67 | '536269399783505950' 68 | ) 69 | group by discord_id 70 | order by messages desc; 71 | --------------------------------------------------------------------------------