├── __init__.py ├── Bot ├── __init__.py ├── cogs │ ├── __init__.py │ ├── utils │ │ ├── __init__.py │ │ └── utils.py │ ├── welcome.py │ ├── osu.py │ ├── repl.py │ ├── weather.py │ └── commands.py ├── requirements.txt ├── storage.py ├── helpformat.py └── bot.py ├── Site ├── __init__.py ├── cogs │ ├── __init__.py │ ├── osu.py │ ├── weather.py │ ├── myanimelist.py │ ├── log.py │ ├── mod.py │ ├── antiraid.py │ ├── memes.py │ └── welcome.py ├── static │ ├── css │ │ ├── morphext.css │ │ ├── recommended-styles.css │ │ ├── bootstrap-tagsinput-typeahead.css │ │ ├── bootstrap-tagsinput.css │ │ └── skin.css │ ├── img │ │ ├── cookie.jpg │ │ ├── Maverun.jpg │ │ ├── favicon.ico │ │ ├── no_logo.png │ │ ├── discord-logo.svg │ │ └── discord.svg │ └── js │ │ ├── morphext.min.js │ │ └── mention.js ├── requirements.txt ├── templates │ ├── faq.html │ ├── sidebar.html │ ├── flash.html │ ├── admins.html │ ├── actions.html │ ├── dashboard.html │ ├── error │ │ ├── code_404_not_found.html │ │ └── code_500_internal_error.html │ ├── welcome.html │ ├── osu │ │ └── index.html │ ├── dash_base.html │ ├── weather │ │ └── index.html │ ├── myanimelist │ │ └── index.html │ ├── level │ │ ├── css_page.html │ │ ├── server_level.html │ │ ├── theme.html │ │ ├── profile_level.html │ │ ├── index.html │ │ └── levels.html │ ├── app │ │ └── index.html │ ├── select-server.html │ ├── plugins.html │ ├── navbar-menu.html │ ├── about.html │ ├── tutorials.html │ ├── profile │ │ └── profile.html │ ├── discourse │ │ ├── index.html │ │ ├── user_link_account.html │ │ ├── category.html │ │ └── trust_role.html │ ├── full-page.html │ ├── custom commands │ │ └── index.html │ ├── memes │ │ ├── index.html │ │ └── memes.html │ ├── after_login.html │ ├── log │ │ └── index.html │ ├── base.html │ ├── core.html │ ├── welcome │ │ └── index.html │ ├── template.html │ ├── mod │ │ └── index.html │ └── antiraid │ │ └── index.html ├── non-cogs │ └── profile.py └── faq.md ├── .gitignore ├── Readme.md └── LICENSE /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Bot/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Site/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Bot/cogs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Site/cogs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Bot/cogs/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Site/static/css/morphext.css: -------------------------------------------------------------------------------- 1 | .morphext > .animated { 2 | display: inline-block; 3 | } -------------------------------------------------------------------------------- /Site/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | requests_oauthlib 3 | redis 4 | gunicorn 5 | Flask-Markdown 6 | osuapi -------------------------------------------------------------------------------- /Site/static/img/cookie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maverun/Nurevam/HEAD/Site/static/img/cookie.jpg -------------------------------------------------------------------------------- /Site/static/img/Maverun.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maverun/Nurevam/HEAD/Site/static/img/Maverun.jpg -------------------------------------------------------------------------------- /Site/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maverun/Nurevam/HEAD/Site/static/img/favicon.ico -------------------------------------------------------------------------------- /Site/static/img/no_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maverun/Nurevam/HEAD/Site/static/img/no_logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | envfile.list 3 | Bot/cogs/rpg.py 4 | secret.json 5 | Bot/cogs/channel.py 6 | Bot/cogs/test.py 7 | Bot/cogs/utils/commands.py 8 | Site/Nurevam_site.log 9 | Bot/bot_log.txt 10 | *.ttf 11 | -------------------------------------------------------------------------------- /Bot/requirements.txt: -------------------------------------------------------------------------------- 1 | # Latest discord.py 2 | discord.py 3 | git+https://github.com/Maverun/Pyanimu 4 | aioredis 5 | redis 6 | PTable 7 | pillow 8 | osuapi 9 | unidecode 10 | GitPython 11 | psutil 12 | lxml 13 | BeautifulSoup4 14 | -------------------------------------------------------------------------------- /Site/cogs/osu.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | import utils 3 | 4 | blueprint = Blueprint('osu', __name__, template_folder='../templates/osu') 5 | 6 | name = "osu" 7 | description = "Allow bot to tell you about stats of your OSU profile" 8 | 9 | db = None #Database 10 | 11 | @utils.plugin_page('osu') 12 | def dashboard(server_id): 13 | return {} 14 | -------------------------------------------------------------------------------- /Site/cogs/weather.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | import utils 3 | 4 | blueprint = Blueprint('weather', __name__, template_folder='../templates/weather') 5 | 6 | name = "weather" 7 | description = "Allow bot to tell you stats in city you ask for" 8 | 9 | db = None #Database 10 | 11 | 12 | @utils.plugin_page('weather') 13 | def dashboard(server_id): 14 | return {} 15 | -------------------------------------------------------------------------------- /Bot/storage.py: -------------------------------------------------------------------------------- 1 | import aioredis 2 | import asyncio 3 | from cogs.utils import utils 4 | 5 | class Redis: 6 | def __init__(self): 7 | self.loop = asyncio.get_event_loop() 8 | self.loop.create_task(self.Start()) 9 | 10 | async def Start(self): 11 | utils.prYellow("AIOREDIS") 12 | self.redis = await aioredis.create_redis((utils.secret["Redis"],6379),encoding='utf8') -------------------------------------------------------------------------------- /Site/static/css/recommended-styles.css: -------------------------------------------------------------------------------- 1 | .mention_name{ 2 | font-size:12px; 3 | } 4 | 5 | .mention_username{ 6 | font-size:12px; 7 | color:#999; 8 | } 9 | 10 | .mention_image{ 11 | float: left; 12 | margin-right:5px; 13 | -webkit-border-radius:3px; 14 | -moz-border-radius: 3px; 15 | border-radius: 3px; 16 | width: 20px; 17 | height: 20px; 18 | } 19 | 20 | .active .mention_username{ 21 | color:#fff; 22 | } -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # This is no longer maintenance 2 | Nurevam is official shutdown. 3 | Reason: [link](https://gist.github.com/Maverun/754ca37d731e5ed9706cf80e6ec03388) 4 | 5 | # Nurevam 6 | This is currenly the Alpha version. 7 | I will update the public version of the bot regularly on this site. 8 | This is the version, that can be run on any server. 9 | 10 | In need of a FAQ, 11 | [please check here](http://nurevam.site/faq) 12 | 13 | 14 | Credit goes to [Cookie](https://github.com/cookkkie/mee6). 15 | The website is based on his website, but heavily edited. 16 | The level system is similar, yet homemade code. 17 | -------------------------------------------------------------------------------- /Site/static/js/morphext.min.js: -------------------------------------------------------------------------------- 1 | /*! Morphext - v2.4.4 - 2015-05-21 */!function(a){"use strict";function b(b,c){this.element=a(b),this.settings=a.extend({},d,c),this._defaults=d,this._init()}var c="Morphext",d={animation:"bounceIn",separator:",",speed:2e3,complete:a.noop};b.prototype={_init:function(){var b=this;this.phrases=[],this.element.addClass("morphext"),a.each(this.element.text().split(this.settings.separator),function(c,d){b.phrases.push(a.trim(d))}),this.index=-1,this.animate(),this.start()},animate:function(){this.index=++this.index%this.phrases.length,this.element[0].innerHTML=''+this.phrases[this.index]+"",a.isFunction(this.settings.complete)&&this.settings.complete.call(this)},start:function(){var a=this;this._interval=setInterval(function(){a.animate()},this.settings.speed)},stop:function(){this._interval=clearInterval(this._interval)}},a.fn[c]=function(d){return this.each(function(){a.data(this,"plugin_"+c)||a.data(this,"plugin_"+c,new b(this,d))})}}(jQuery); -------------------------------------------------------------------------------- /Bot/helpformat.py: -------------------------------------------------------------------------------- 1 | from discord.ext.commands import help,Group 2 | import discord 3 | 4 | class Custom_format(help.DefaultHelpCommand): 5 | def add_indented_commands(self,commands,*, heading = None, max_size=None, indent = 0): 6 | if not commands: return 7 | if heading: self.paginator.add_line(heading) 8 | max_size = max_size or self.get_max_size(commands) 9 | 10 | get_width = discord.utils._string_width 11 | uni = "├" 12 | max_count = len(commands) 13 | for index, command in enumerate(commands, start=1): 14 | if index == max_count: uni = "└" 15 | name = command.name 16 | width = max_size - (get_width(name) - len(name)) 17 | entry = '{0}{uni}{1:<{width}} {2}'.format( (self.indent + indent) * ' ', name, command.short_doc, width=width,uni = uni) 18 | self.paginator.add_line(self.shorten_text(entry)) 19 | if(isinstance(command,Group)): 20 | return self.add_indented_commands(command.commands,indent = self.indent + indent) 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Maverun 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 | -------------------------------------------------------------------------------- /Site/cogs/myanimelist.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | import random 3 | import utils 4 | 5 | anime_picture=[["http://31.media.tumblr.com/tumblr_m3z4xrHVZi1rw2jaio1_500.gif","I will wait for your commands! <3"], 6 | ["http://media3.giphy.com/media/ErZ8hv5eO92JW/giphy.gif","NICE JAB! USE IT AS YOU WANT!"]] 7 | 8 | 9 | blueprint = Blueprint('myanimelist',__name__,template_folder='../templates/myanimelist') 10 | 11 | name = "Anime and Manga" 12 | description = "Search the web for your favorite anime and manga. Allow to add anime/manga to your Anilist list. Not to mention, able to check out what source of this certain anime came from!" 13 | 14 | db = None #Database 15 | 16 | #Anime 17 | @utils.plugin_page("myanimelist") 18 | def dashboard(server_id): 19 | number =random.randint(0,len(anime_picture)-1) 20 | get_role = utils.resource_get("/guilds/{}".format(server_id)) 21 | guild_roles = get_role['roles'] 22 | role = db.smembers('{}:Memes:editor_role'.format(server_id)) or [] 23 | channel = utils.get_channel(server_id) 24 | admin_role = list(filter(lambda r: r['name'] in role or r['id'] in role, guild_roles)) 25 | return {"Info":anime_picture[number],"guild_roles":guild_roles,"admin_roles":admin_role,"channel":channel} 26 | -------------------------------------------------------------------------------- /Site/static/css/bootstrap-tagsinput-typeahead.css: -------------------------------------------------------------------------------- 1 | /* 2 | * bootstrap-tagsinput v0.8.0 3 | * 4 | */ 5 | 6 | .twitter-typeahead .tt-query, 7 | .twitter-typeahead .tt-hint { 8 | margin-bottom: 0; 9 | } 10 | 11 | .twitter-typeahead .tt-hint 12 | { 13 | display: none; 14 | } 15 | 16 | .tt-menu { 17 | position: absolute; 18 | top: 100%; 19 | left: 0; 20 | z-index: 1000; 21 | display: none; 22 | float: left; 23 | min-width: 160px; 24 | padding: 5px 0; 25 | margin: px 0 0; 26 | list-style: none; 27 | font-size: 14px; 28 | background-color: #222222; 29 | border: 1px solid #cccccc; 30 | border: 1px solid rgba(0, 0, 0, 0.15); 31 | border-radius: 4px; 32 | -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); 33 | box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); 34 | background-clip: padding-box; 35 | cursor: pointer; 36 | } 37 | 38 | .tt-suggestion { 39 | display: block; 40 | padding: 3px 20px; 41 | clear: both; 42 | font-weight: normal; 43 | line-height: 1.428571429; 44 | color: #0ce3ac; 45 | white-space: nowrap; 46 | } 47 | 48 | .tt-suggestion:hover, 49 | .tt-suggestion:focus { 50 | color: #ffffff; 51 | text-decoration: none; 52 | outline: 0; 53 | background-color: #428bca; 54 | } 55 | -------------------------------------------------------------------------------- /Site/static/img/discord-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Site/templates/faq.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 | {{text|markdown}} 27 |
28 |
29 |
30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /Site/templates/sidebar.html: -------------------------------------------------------------------------------- 1 | 21 | 26 | -------------------------------------------------------------------------------- /Site/cogs/log.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, render_template, request, redirect, url_for, flash 2 | import logging 3 | import utils 4 | 5 | log = logging.getLogger("Nurevam.site") 6 | 7 | blueprint = Blueprint('log', __name__, template_folder='../templates/log') 8 | 9 | name = "log" 10 | description = "Allow bot give you a log of what happen,edit,delete etc on channel" 11 | 12 | db = None #Database 13 | 14 | 15 | @utils.plugin_page('log') 16 | def dashboard(server_id): 17 | log.info("loading cog page") 18 | config = db.hgetall("{}:Log:Config".format(server_id)) 19 | channel = utils.get_channel(server_id) 20 | if config.get("channel", False) is False: 21 | log_channel = server_id 22 | else: 23 | log_channel = config['channel'] 24 | return { 25 | 'guild_channel': channel, 26 | "log_channel": log_channel, 27 | 'config': config 28 | } 29 | 30 | 31 | @blueprint.route('/update/', methods=['POST']) 32 | @utils.plugin_method 33 | def update_log(server_id): 34 | list_point = dict(request.form) 35 | list_point.pop('_csrf_token', None) 36 | path = "{}:Log:Config".format(server_id) 37 | log_bool = False 38 | db.delete(path) 39 | for x in list_point: 40 | if request.form.get(x): 41 | log_bool = True 42 | db.hset(path, x, request.form.get(x)) 43 | if log_bool: 44 | db.sadd("Info:Log", server_id) 45 | flash('Settings updated!', 'success') 46 | log.info("Clear") 47 | return dashboard(server_id=server_id) 48 | -------------------------------------------------------------------------------- /Site/templates/flash.html: -------------------------------------------------------------------------------- 1 | 21 | {% with messages = get_flashed_messages(with_categories=true) %} 22 | {% for category,message in messages %} 23 |
24 | 25 | {{ message }} 26 |
27 | {% endfor %} 28 | {% endwith %} 29 | -------------------------------------------------------------------------------- /Site/templates/admins.html: -------------------------------------------------------------------------------- 1 | 21 |

Bot admins

22 |
23 |
24 |

25 | {{session['user']['username']}} #{{session['user']['discriminator']}}

26 |
27 | 28 |
29 | -------------------------------------------------------------------------------- /Site/static/css/bootstrap-tagsinput.css: -------------------------------------------------------------------------------- 1 | /* 2 | * bootstrap-tagsinput v0.8.0 3 | * 4 | */ 5 | 6 | .bootstrap-tagsinput { 7 | background-color: #e0e0e0; 8 | border: 1px solid #ccc; 9 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 10 | display: inline-block; 11 | padding: 4px 6px; 12 | color: #555; 13 | vertical-align: middle; 14 | border-radius: 4px; 15 | max-width: 100%; 16 | line-height: 25px; 17 | cursor: text; 18 | } 19 | .bootstrap-tagsinput input { 20 | border: none; 21 | box-shadow: none; 22 | outline: none; 23 | background-color: transparent; 24 | padding: 0 6px; 25 | margin: 0; 26 | width: auto; 27 | max-width: inherit; 28 | } 29 | .bootstrap-tagsinput.form-control input::-moz-placeholder { 30 | color: #777; 31 | opacity: 1; 32 | } 33 | .bootstrap-tagsinput.form-control input:-ms-input-placeholder { 34 | color: #777; 35 | } 36 | .bootstrap-tagsinput.form-control input::-webkit-input-placeholder { 37 | color: #777; 38 | } 39 | .bootstrap-tagsinput input:focus { 40 | border: none; 41 | box-shadow: none; 42 | } 43 | .bootstrap-tagsinput .tag { 44 | margin-right: 2px; 45 | color: white; 46 | } 47 | .bootstrap-tagsinput .tag [data-role="remove"] { 48 | margin-left: 8px; 49 | cursor: pointer; 50 | } 51 | .bootstrap-tagsinput .tag [data-role="remove"]:after { 52 | content: "x"; 53 | padding: 0px 2px; 54 | } 55 | .bootstrap-tagsinput .tag [data-role="remove"]:hover { 56 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 57 | } 58 | .bootstrap-tagsinput .tag [data-role="remove"]:hover:active { 59 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 60 | } 61 | -------------------------------------------------------------------------------- /Site/cogs/mod.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, render_template,request, redirect,url_for 2 | import logging 3 | import utils 4 | 5 | log = logging.getLogger("Nurevam.site") 6 | 7 | blueprint = Blueprint('mod', __name__, template_folder='../templates/mod') 8 | 9 | name = "mod" 10 | description = "A simple mod command, allow to clean message! Be itself,role,person or all!" 11 | 12 | db = None #Database 13 | 14 | @utils.plugin_page('mod') 15 | def dashboard(server_id): 16 | log.info("Load cogs pages") 17 | db_admin_role = db.smembers('{}:Mod:admin_roles'.format(server_id)) or [] 18 | db_mute_role = db.smembers('{}:Mod:mute_roles'.format(server_id)) or [] 19 | get_role = utils.resource_get("/guilds/{}".format(server_id)) 20 | guild_roles = get_role['roles'] 21 | admin_role = list(filter(lambda r: r['name'] in db_admin_role or r['id'] in db_admin_role, guild_roles)) 22 | mute_role = list(filter(lambda r: r['name'] in db_mute_role or r['id'] in db_mute_role, guild_roles)) 23 | return {"admin_roles": admin_role, "mute_roles":mute_role,"guild_roles": guild_roles} 24 | 25 | @blueprint.route('/update/', methods=['POST']) 26 | @utils.plugin_method 27 | def update_mod(server_id): 28 | admin_roles = request.form.get('admin_roles').split(',') 29 | mute_roles = request.form.get("mute_roles").split(",") 30 | db.delete("{}:Mod:admin_roles".format(server_id)) 31 | db.delete("{}:Mod:mute_roles".format(server_id)) 32 | if len(admin_roles) > 0: 33 | db.sadd("{}:Mod:admin_roles".format(server_id), *admin_roles) 34 | if len(mute_roles) > 0 : 35 | db.sadd("{}:Mod:mute_roles".format(server_id), *mute_roles) 36 | return dashboard(server_id=server_id) 37 | -------------------------------------------------------------------------------- /Site/templates/actions.html: -------------------------------------------------------------------------------- 1 | 21 |

Actions

22 | 33 | -------------------------------------------------------------------------------- /Site/templates/dashboard.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 |
26 | {% include 'plugins.html' %} 27 |
28 |
29 | {% include 'actions.html' %} 30 |
31 |
32 | {% include 'welcome.html' %} 33 |
34 |
35 |
36 | 37 | {% endblock %} 38 | -------------------------------------------------------------------------------- /Site/templates/error/code_404_not_found.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 |
27 | 28 |

Oh no..This page wasn't found! (Error 404 Page Not Found)

29 |
30 |
31 |
32 |
33 | {% endblock %} 34 | -------------------------------------------------------------------------------- /Site/templates/welcome.html: -------------------------------------------------------------------------------- 1 | 21 |

Welcome!

22 |
23 |
24 |

25 | {{session['user']['username']}} #{{session['user']['discriminator']}}

26 | Here you'll be able to enable/disable plugins and change the bot config.

27 | Try out the Levels!

28 | Anyone who has server management permissions in your server can access this dashboard. 29 |

30 |
31 | 32 |
33 | -------------------------------------------------------------------------------- /Site/templates/error/code_500_internal_error.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 |
27 |

OH! Uhm... Hello there... There seems to be a problem... Please try again. If it still happens, please wait for me to fix (report to owner would be great) (Error: 500 Internal Server Error)

28 |
Maverun (´・ω・`)#2781
29 |
30 |
31 |
32 |
33 | {% endblock %} 34 | -------------------------------------------------------------------------------- /Site/templates/osu/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | 27 |
28 |

Osu Disable

29 | {% include 'flash.html' %} 30 |
31 |

32 |

Type !osu maverun in your chat!
33 |

34 |
35 |
36 | 37 |
38 |
39 | 40 | {% endblock %} 41 | -------------------------------------------------------------------------------- /Site/templates/dash_base.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'base.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 |
27 |

28 | {% if server['icon'] %} 29 | 30 | {% endif %} 31 | {{server['name']}}

32 |
33 |
34 |
35 |
36 | {% block dash_content %} 37 | {% endblock %} 38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /Site/templates/weather/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | 27 |
28 |

Weather Disable

29 | {% include 'flash.html' %} 30 |
31 |

32 |

Type !weather london or for more accurate, !weather london uk
33 |

34 |
35 |
36 | 37 |
38 |
39 | {% endblock %} 40 | -------------------------------------------------------------------------------- /Site/templates/myanimelist/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 |
27 |

Anime and Manga Disable

28 | {% include 'flash.html' %} 29 |
30 |

31 | 32 |

{{Info[1]}}

33 |
Type !anime Trigun and
!manga Berserk in your chat!
34 |

35 |
36 |
37 |
38 |
39 | 40 | {% endblock %} 41 | -------------------------------------------------------------------------------- /Site/static/css/skin.css: -------------------------------------------------------------------------------- 1 | .home-navbar { 2 | margin-bottom: 0; 3 | padding-top: 10px; 4 | } 5 | 6 | .beta-badge{ 7 | background-color: #404040; 8 | } 9 | 10 | bootstrap-tagsinput{ 11 | width:100% !important;} 12 | 13 | label-info{ 14 | background-color:#008cba!important;} 15 | .dashboard-nav{ 16 | margin-bottom: 0; 17 | } 18 | 19 | .jumbotron small{ 20 | color:#FFF; 21 | } 22 | 23 | .vertical-align { 24 | display: flex; 25 | flex-direction: row; 26 | } 27 | 28 | .vertical-align > [class^="col-"], 29 | .vertical-align > [class*=" col-"] { 30 | display: flex; 31 | align-items: center; /* Align the flex-items vertically */ 32 | } 33 | .vertical-align h2{ 34 | margin: 0; 35 | padding: 0; 36 | } 37 | 38 | .home-jumbotron{ 39 | background-color: #1d1d1d; 40 | min-height: 100%; 41 | min-height: 100vh; 42 | display: flex; 43 | padding:0; 44 | margin: 0; 45 | align-items: center; 46 | } 47 | 48 | .dashboard-jumbotron{ 49 | background-color: #222222; 50 | color:#FFF; 51 | } 52 | .profile-image{ 53 | height: 21px; 54 | width: 21px; 55 | line-height: 21px; 56 | } 57 | .server-logo{ 58 | width:100px; 59 | height: 100px; 60 | margin:4px; 61 | } 62 | .disabled{ 63 | background-color:#e99002; 64 | } 65 | .soon{ 66 | background-color: #EFEFEF; 67 | color:#000; 68 | } 69 | 70 | .discord-logo1{ 71 | width:5em; 72 | margin-top:0.15em; 73 | } 74 | .discord-logo2{ 75 | width:5em; 76 | margin-bottom:0.2em; 77 | } 78 | 79 | .btn-home{ 80 | background-color: #3b5998; 81 | color:#cfcfcf; 82 | } 83 | .btn-home:hover{ 84 | background-color: #8b9dc3; 85 | color:#FFF; 86 | } 87 | .btn-about{ 88 | background-color: #3b5998; 89 | color:#cfcfcf 90 | } 91 | .btn-about:hover{ 92 | background-color: #8b9dc3; 93 | color:#FFF; 94 | } 95 | .v-align { 96 | float: none; 97 | display: inline-block; 98 | vertical-align: middle; 99 | } 100 | 101 | .home-body{ 102 | background-color: #1D1D1D; 103 | color:#FFF; 104 | overflow: auto; 105 | } 106 | -------------------------------------------------------------------------------- /Site/static/img/discord.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Site/templates/level/css_page.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 |
24 |
25 | {% set csrf = csrf_token() %} 26 |
27 | {% include 'flash.html' %} 28 |
29 | 30 |
31 |
32 | Enter css below in test box, once you are done, click update. 33 | To remove them, leave it a blank. 34 |
35 |
36 | 37 | 38 | 39 |
40 |
41 | 42 |
43 |
44 | {%endblock%} 45 | -------------------------------------------------------------------------------- /Site/templates/app/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 |
27 |

Introducing Nurevam the bot

28 |

Total Servers: {{info['Server']}}, Total Users: {{info['Member']}}

29 |

for everyone in your server

30 |

31 | Add to discord 32 | About 33 | FAQ 34 |

35 |
36 | 38 |
39 |
40 |
41 | {% endblock %} 42 | -------------------------------------------------------------------------------- /Site/templates/select-server.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 |
27 |

Select a server :

28 |
29 | {% if user_servers %} 30 | 36 | 44 | {% else %} 45 |

Oh no! It looks like you don't have any servers!

46 |

Go create one !
I'm waiting for you right here!

47 | {% endif %} 48 |
49 |
50 |
51 | 52 |
53 |
54 | {% endblock %} -------------------------------------------------------------------------------- /Site/templates/plugins.html: -------------------------------------------------------------------------------- 1 | 21 |

Plugins

22 | 42 | -------------------------------------------------------------------------------- /Site/templates/navbar-menu.html: -------------------------------------------------------------------------------- 1 | 21 | 47 | -------------------------------------------------------------------------------- /Site/templates/about.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 |
27 |

Star Features

28 |
29 |
30 | {% for cog in plugin_list %} 31 |

{{cog[0]}}

32 |

{{cog[1]|safe}}

33 |
34 | {% endfor %} 35 |
36 |
37 |
39 |

Creator?

40 |
41 |

Maverun

42 |

Contributors

43 |
44 |
45 |
46 |

Cookie

47 |

The orignal creator of Mee6. Nurevam was inspired by his bot/website. Receive his permission for webs used..

48 |
49 |
50 |
51 |
52 |
53 |
54 | {% endblock %} 55 | -------------------------------------------------------------------------------- /Bot/cogs/welcome.py: -------------------------------------------------------------------------------- 1 | from .utils import utils 2 | from discord.ext import commands 3 | import traceback 4 | import datetime 5 | import discord 6 | 7 | class Welcome(commands.Cog): #Allow to welcome new members who join guild. If it enable, will send them a message. 8 | def __init__(self,bot): 9 | self.bot = bot 10 | self.redis = bot.db.redis 11 | 12 | async def error(self,owner,e): 13 | # await owner.send("There is an error with a newcomer, please report this to the creator.\n {}".format(e)) 14 | Current_Time = datetime.datetime.utcnow().strftime("%b/%d/%Y %H:%M:%S UTC") 15 | utils.prRed(Current_Time) 16 | utils.prRed("Error!") 17 | utils.prRed(traceback.format_exc()) 18 | error = '```py\n{}\n```'.format(traceback.format_exc()) 19 | await self.bot.owner.send("```py\n{}```".format(Current_Time + "\n" + "ERROR!") + "\n" + error) 20 | 21 | @commands.Cog.listener() 22 | async def on_member_join(self,member): 23 | if await self.redis.hget("{}:Config:Cogs".format(member.guild.id),"welcome") == "on": 24 | config = await self.redis.hgetall("{}:Welcome:Message".format(member.guild.id)) 25 | try: 26 | if config.get("enable_message") == "on": 27 | msg = config["message"].format(user=member.name,server=member.guild,user_mention=member.mention) 28 | if config.get("enable_delete") == "on": 29 | time = int(config["delete_msg"]) 30 | else: 31 | time = None 32 | 33 | if config.get("whisper") == "on": 34 | await member.send(msg,delete_after = time) 35 | else: 36 | await self.bot.get_channel(int(config["channel"])).send(msg,delete_after = time) 37 | 38 | #Now assign a roles. 39 | if config.get("role") == "on": 40 | role_list = await self.redis.smembers('{}:Welcome:Assign_Roles'.format(member.guild.id)) 41 | role_obj=[] 42 | for x in role_list: 43 | if x == '': #if it return empty string 44 | continue 45 | # role_obj.append(discord.utils.get(member.guild.roles,id=int(x))) 46 | role_obj.append(member.guild.get_role(int(x))) 47 | try: 48 | await member.add_roles(*role_obj,reason = "User has join the server,and an admin request to add role(s) to new person") 49 | except discord.Forbidden: 50 | pass #if unable to add user 51 | except discord.NotFound: 52 | pass #if it cant find that user. Assume it left server. 53 | 54 | except Exception as e: 55 | await self.error(member.guild.owner, e) 56 | 57 | def setup(bot): 58 | bot.add_cog(Welcome(bot)) 59 | -------------------------------------------------------------------------------- /Site/non-cogs/profile.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, render_template, request, redirect, url_for, flash,session 2 | # from pyanimu import Anilist,UserStatus_Anilist, connectors 3 | from requests_oauthlib import OAuth2Session 4 | import requests 5 | import logging 6 | import utils 7 | 8 | log = logging.getLogger("Nurevam.site") 9 | 10 | blueprint = Blueprint('profile', __name__, template_folder='../templates/profile') 11 | 12 | db = None #Database 13 | 14 | osu_api = None 15 | 16 | @blueprint.route('/') 17 | @utils.require_auth 18 | def profile(): 19 | """ 20 | A user profile. 21 | It's purpose is for globals setting across server. 22 | """ 23 | user = session['user'] 24 | setting = db.hgetall("Profile:{}".format(user["id"])) 25 | return render_template('profile.html',user=user,setting=setting,anilist_cleint_id = utils.data_info.anilist_id,anilist_redirect = url_for('profile.anilist_request',_external=True)) 26 | 27 | @blueprint.route('/update', methods=['POST']) 28 | @utils.require_auth 29 | def update_profile(): #Update a setting. 30 | list_point = dict(request.form) 31 | list_point.pop('_csrf_token',None) 32 | path = "Profile:{}".format(session['user']['id']) 33 | warning = False 34 | warning_msg = "One of those have failed, Please double check {} " 35 | warning_list =[] 36 | for x in list_point: 37 | print(x) 38 | if request.form.get(x) == "": 39 | db.hdel(path,x) 40 | continue 41 | elif x == "osu": 42 | results = osu_api.get_user(request.form.get(x)) 43 | if results == []: 44 | warning = True 45 | warning_list.append(x) 46 | continue 47 | db.hset(path,x,request.form.get(x)) 48 | if warning: 49 | flash(warning_msg.format(",".join(warning_list)), 'warning') 50 | else: 51 | flash('Settings updated!', 'success') 52 | return redirect(url_for('profile.profile')) 53 | 54 | def status_site(site): 55 | r = requests.get(site) 56 | if r.status_code == 200: 57 | return True 58 | else: 59 | return False 60 | 61 | @blueprint.route('/anilist/') 62 | @utils.require_auth 63 | def anilist_request(): 64 | code = request.args.get("code") 65 | header = {'Content-Type': 'application/json','Accept': 'application/json'} 66 | r = requests.post("https://anilist.co/api/v2/oauth/token",json = { 67 | 'client_id':str(utils.data_info.anilist_id), 68 | 'client_secret':utils.data_info.anilist_token, 69 | 'redirect_uri':url_for('profile.anilist_request',_external=True), 70 | 'grant_type': 'authorization_code', 71 | 'code':code},headers=header) 72 | data =r.json() 73 | user = session['user'] 74 | 75 | db.hmset("Profile:{}:Anilist".format(user["id"]),data) 76 | print("Successfully create token for ",user["id"]," - ",user["username"]) 77 | flash("Anilist update!","success") 78 | return redirect(url_for('profile.profile')) 79 | 80 | -------------------------------------------------------------------------------- /Site/templates/tutorials.html: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Tutorials of command.ext 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 57 | 58 |
59 |
60 |
61 | {{text|markdown}} 62 |
63 |
64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /Site/faq.md: -------------------------------------------------------------------------------- 1 | ##Maverun 2 | 3 | 4 | 5 | # FAQ 6 | --- 7 | 8 | ##How do I get Nurevam to join my server? 9 | >Make sure you have the `Manage Server` permission, log in on the website with your discord account and you will see a list of the servers that you have the `Manage Server` permission for. 10 | Select the server you want Nurevam to join. 11 | 12 | ##How can I enable the plugins? 13 | >Select the plugin you want to run and confirm that you want to enable it. 14 | 15 | ##Why did a command not working? 16 | >Please make sure you have the respective plugin enabled. It may ask for the roles, permissions etc, also checked if this command is a subcommand which you will need to use the chain command. 17 | 18 | ##What is the subcommand? 19 | >The subcommand comes after a main command. For example: role from mod plugin or clean as well are subcommands, so you would have to say !role add @person role_name 20 | 21 | >If i write `!clean`, it will just clean all bot messages, however if i write `!clean all` it will clean all message, including user messages. Role does the same thing with add/remove. 22 | 23 | >Bascially, it is just `
` 24 | 25 | ##What is my profile? 26 | >Your profile is a global setting for all servers with Nurevam. If you, for example, have a Anilist profile and enter your username on the website, you don't have to write down `!anilist `, but instead just `!anilist` and the bot will do the work for you! 27 | 28 | ##Why are there so many permissions? 29 | >It is entirely up to you, which permissions you give. I included all permission, so you can pick. I would recommend leaving the `manage message` permission checked, so it can delete your and it's own messages (with the `clean` command). 30 | 31 | ##What is this log plugin? 32 | >The log plugin will keep you updated on what happens to the server. For example: Did a user delete a message, change his avatar, etc. 33 | >This is, so that you can stay informed. Normally, this is for admins/mods who want to be kept informed and not confused about what happens.(I kinda don't like the edit/delete message, it is the user's privacy, right...) 34 | 35 | ##I got request about... 36 | >You got an idea or any request? Feel free to PM me or [join the server here](https://discordapp.com/invite/010erZHcMcH15gTLZ) and I will think about it. 37 | 38 | ##I found a bug/problem... 39 | >Really?! Rats, those are hiding from me! Please PM me or [join the server here](https://discordapp.com/invite/010erZHcMcH15gTLZ), I will gladly do my best to fix them! 40 | 41 | ##I want to make a plugin... 42 | >Go for it! If you don't understand how to set it up, please inform me, I will try to set up tutorials. You will need some knowledge on python3.5. Check requirements.txt and see what is required. 43 | 44 | >I will review it and give feedback on what you need to improve on! 45 | 46 | ##This is a copycat of Mee6! 47 | >I have got the permission from the creator of Mee6, Cookie. He gave his approval and said "go for it!". Furthermore, my code is different to his and the only similarity we have is the website design. 48 | 49 | ##I got a question about this FAQ or something else... 50 | >Feel free to PM me or [join the server here](https://discordapp.com/invite/010erZHcMcH15gTLZ). I will gladly answer your question and add something to this FAQ. 51 | -------------------------------------------------------------------------------- /Site/templates/level/server_level.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'base.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 |

Server Leaderboard

27 |
28 | {% for server in server_list %} 29 |
30 |
31 |
32 |

#{{loop.index}}

33 |
34 | 41 |
42 |

{{server[0]}}

43 |
44 |
45 |
{{server[3]}} / {{server[4]}} XP
46 |
47 |
48 |
49 |
50 |
51 |

Level {{server[6]}}

52 |
53 |
54 |
55 | {% endfor %} 56 |
57 |
58 | 59 |
60 |
61 | 62 | 63 | {% endblock %} 64 | -------------------------------------------------------------------------------- /Site/cogs/antiraid.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, request, redirect, url_for,flash 2 | import logging 3 | import utils 4 | 5 | log = logging.getLogger("Nurevam.site") 6 | 7 | blueprint = Blueprint('antiraid', __name__, template_folder='../templates/antiraid') 8 | 9 | name = "Anti Raid (BETA)" 10 | description = "Allow to monitor server and ensure there is no raid. Note: This is beta plugin" 11 | 12 | db = None #Database 13 | 14 | default_option = { 15 | #Invite link and any link 16 | "invite_link": "0", 17 | "any_link":"0", 18 | "any_link_time":"300", 19 | 20 | #massive ping mention. 21 | "multi_ping":"0", 22 | "multi_ping_limit":10, 23 | 24 | #Joining user to server, checking their age 25 | "member_age": "0", 26 | "member_age_time": "3600", # 1 hrs, it is min 27 | 28 | #if multi people join at once within x min and total of member joining at least y 29 | "multi_people": "0", 30 | "multi_people_limit": "10", # if 10 join within x min, ban 31 | "multi_people_time": "300", # 5 min, if ^x join within 5 min, do ban or any 32 | 33 | #if user spam message, count x msg and y min also checking ratio of similar 34 | "spam_msg": "0", 35 | "spam_msg_count": "10", # if user spam 10 same/similar message within x, do action 36 | "spam_msg_percent": "90", # how similar is message percent 37 | "spam_msg_time": "20", # x sec limit 38 | } 39 | option_setting = [ 40 | {"id":'0',"name":"Nothing"}, 41 | #{"id":1,"name":"Warning"}, 42 | {"id":'2',"name":"Role Grant"}, 43 | {"id":'3',"name":"Kick"}, 44 | {"id":'4',"name":"Softban"}, 45 | {"id":'5',"name":"Ban"}, 46 | ] 47 | 48 | #there will be 5 level 49 | #0 is nothing 50 | #1 is warning user 51 | #2 is role grant 52 | #3 is kick 53 | #4 is softban 54 | #5 is ban 55 | 56 | @utils.plugin_page('antiraid') 57 | def dashboard(server_id): 58 | info = db.hgetall("{}:AntiRaid:Config".format(server_id)) or default_option 59 | db_mute_role = db.smembers('{}:AntiRaid:mute_roles'.format(server_id)) or [] 60 | get_role = utils.resource_get("/guilds/{}".format(server_id)) 61 | guild_roles = get_role['roles'] 62 | mute_role = list(filter(lambda r: r['name'] in db_mute_role or r['id'] in db_mute_role, guild_roles)) 63 | 64 | return {"option_data":option_setting,"config":info,"mute_roles":mute_role,"guild_roles":guild_roles} 65 | 66 | @blueprint.route('/update/', methods=['POST']) 67 | @utils.plugin_method 68 | def update_antiraid(server_id): 69 | log.info(request.form) 70 | data = dict(request.form) 71 | data.pop("_csrf_token",None) 72 | role = data.pop("mute_roles",None) 73 | db.delete("{}:AntiRaid:mute_roles".format(server_id)) 74 | if role is not None: 75 | db.sadd('{}:AntiRaid:mute_roles'.format(server_id),*role) 76 | old_data = data.copy() 77 | data = {key:value[0] for key,value in data.items() if value[0].isdigit()} 78 | if len(old_data) != len(data): 79 | flash("At least one of those values has to be positive INTEGER",'warning') 80 | return 81 | db.hmset("{}:AntiRaid:Config".format(server_id),data) 82 | db.sadd("Info:AntiRaid",server_id) 83 | flash('Settings updated!', 'success') 84 | return dashboard(server_id=server_id) 85 | -------------------------------------------------------------------------------- /Site/templates/profile/profile.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 | 24 |
25 |
26 |
27 | {% set csrf = csrf_token() %} 28 | {% include 'flash.html' %} 29 | 30 |
31 |
32 |
33 | {% if user["avatar"] !=None %} 34 |
35 | {% else %} 36 |
37 | {%endif%} 38 |

{{user["username"]}}#{{user["discriminator"]}}

39 |
40 |
41 |
42 |
43 |
44 |
45 | Login with AniList 46 |
47 |
48 |
49 |
50 |
51 |
52 | 53 | 54 | 56 |
57 |
58 |
59 | 60 |
61 |
62 | 63 | 64 | 65 | {% endblock %} 66 | 67 | 68 | -------------------------------------------------------------------------------- /Site/cogs/memes.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, render_template, request, redirect, url_for, flash 2 | import requests 3 | import logging 4 | import utils 5 | 6 | log = logging.getLogger("Nurevam.site") 7 | 8 | 9 | blueprint = Blueprint('memes', __name__, template_folder='../templates/memes') 10 | 11 | name = "memes" 12 | description = "Allow to post a custom memes you like!" 13 | 14 | db = None #Database 15 | 16 | 17 | @utils.plugin_page('memes') 18 | def dashboard(server_id): 19 | log.info("loading cog pages") 20 | db_role = db.smembers('{}:Memes:editor_role'.format(server_id)) or [] 21 | get_role = utils.resource_get("/guilds/{}".format(server_id)) 22 | guild_roles = get_role['roles'] 23 | role = list(filter(lambda r: r['name'] in db_role or r['id'] in db_role, guild_roles)) 24 | return {"roles": role, "guild_roles": guild_roles} 25 | 26 | 27 | @blueprint.route('/update/', methods=['POST']) 28 | @utils.plugin_method 29 | def update_memes(server_id): 30 | roles = request.form.get('roles').split(',') 31 | db.delete("{}:Memes:editor_role".format(server_id)) 32 | if len(roles) > 0: 33 | db.sadd("{}:Memes:editor_role".format(server_id), *roles) 34 | return dashboard(server_id=server_id) 35 | 36 | @blueprint.route("///") 37 | @utils.require_role 38 | def memes(cog, server_id): 39 | meme_link = db.hgetall("{}:Memes:link".format(server_id)) 40 | return render_template("memes.html", data_memes=meme_link, server_id=server_id) 41 | 42 | 43 | @blueprint.route('/add///', methods=['POST']) 44 | @utils.require_role 45 | def add_memes(cog, server_id): 46 | name = request.form.get("meme_name") 47 | link = request.form.get("meme_link") 48 | status = utils.check_link(link) 49 | if status == 0: # if is true 50 | if name in db.smembers("{}:Memes:name".format(server_id)): 51 | flash("This name already exists!", "warning") 52 | else: 53 | db.hset("{}:Memes:link".format(server_id), name, link) 54 | db.sadd("{}:Memes:name".format(server_id), name) 55 | flash("You have add a new memes!", "success") 56 | return redirect(url_for("memes.memes", server_id=server_id, cog="memes")) 57 | 58 | 59 | @blueprint.route('/update//', methods=['POST']) 60 | @utils.plugin_method 61 | def edit_memes(server_id, name): 62 | new_name = request.form.get("meme_name") 63 | link = request.form.get("meme_link") 64 | status = utils.check_link(link) 65 | if status == 0: 66 | # delete old database 67 | db.hdel("{}:Memes:link".format(server_id), name) 68 | db.srem("{}:Memes:name".format(server_id), name) 69 | # adding, if there is a way to rename them in hash, that would be great... 70 | db.hset("{}:Memes:link".format(server_id), new_name, link) 71 | db.sadd("{}:Memes:name".format(server_id), new_name) 72 | flash("Update data!", "success") 73 | return redirect(url_for("memes.memes", server_id=server_id, cog="memes")) 74 | 75 | 76 | @blueprint.route('/delete///', methods=['GET']) 77 | @utils.plugin_method 78 | def delete_memes(server_id, name): 79 | # Deleting data 80 | db.hdel("{}:Memes:link".format(server_id), name) 81 | db.srem("{}:Memes:name".format(server_id), name) 82 | return redirect(url_for("memes.memes", server_id=server_id, cog="Memes")) 83 | 84 | -------------------------------------------------------------------------------- /Site/templates/discourse/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 |

Discourse Disable

29 | {% include 'flash.html' %} 30 | 31 | 32 | {{template.text_box("domain","Domain link","Enter the Domain link here: for example https://meta.discourse.org",config['domain'])}} 33 | {{template.text_box("api_key","API Key","Enter API Key",config['api_key'])}} 34 | {{template.text_box("username","Username","Enter the username",config['username'])}} 35 | {{template.channel_list("channel","Channel for posting info",guild_channel,"Note,make sure Nurevam are able to speak on that channel!",discourse_channel)}} 36 | {{template.text_box("msg","Message Template","Allow to set custom message, how you want it look like! Note: \\t make 4 spaces, \\n add newline,{title} is title of thread, {author} is creator of thread, and {link} is link to thread.", msg_template.replace("'","")[1:])}} 37 | 38 |
39 | For people who want to have each category for different each channel can click this 40 | 41 |
42 | For people who want Nurevam auto grant roles to people from Discourse Trust Level can click this 43 |
44 | 45 | 46 | 47 | 48 |
49 |
50 |
51 | 52 | {% endblock %} 53 | -------------------------------------------------------------------------------- /Site/cogs/welcome.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, request, redirect, url_for,flash 2 | import logging 3 | import utils 4 | 5 | log = logging.getLogger("Nurevam.site") 6 | 7 | blueprint = Blueprint('welcome', __name__, template_folder='../templates/welcome') 8 | 9 | name = "welcome" 10 | description = "Send a welcome/greet message to newcomer who just join your server!" 11 | 12 | db = None #Database 13 | 14 | @utils.plugin_page('welcome') 15 | def dashboard(server_id): 16 | log.info("loading cogs page") 17 | default_message = "{user}, welcome to **{server}**!" 18 | get_message = db.hget("{}:Welcome:Message".format(server_id), "message") 19 | if get_message is None: 20 | db.hset("{}:Welcome:Message".format(server_id), "message", default_message) 21 | get_message = default_message 22 | config = db.hgetall("{}:Welcome:Message".format(server_id)) 23 | channel = utils.get_channel(server_id) 24 | delete_msg = db.hget("{}:Welcome:Message".format(server_id), "delete_msg") or 0 25 | if config.get("channel", False) is False: 26 | welcome_channel = server_id 27 | else: 28 | welcome_channel = config['channel'] 29 | 30 | db_assign_role = db.smembers('{}:Welcome:Assign_Roles'.format(server_id)) or [] 31 | get_role = utils.resource_get("/guilds/{}".format(server_id)) 32 | guild_roles = get_role['roles'] 33 | assign_role = list(filter(lambda r: r['name'] in db_assign_role or r['id'] in db_assign_role, guild_roles)) 34 | return { 35 | 'guild_channel': channel, 36 | "welcome_channel": welcome_channel, 37 | 'assign_role': assign_role, 38 | 'guild_roles': guild_roles, 39 | 'message': get_message, 40 | 'config': config, 41 | 'delete_msg': delete_msg} 42 | 43 | 44 | @blueprint.route('/update/', methods=['POST']) 45 | @utils.plugin_method 46 | def update_welcome(server_id): 47 | welcome_message = request.form.get('message') 48 | channel = request.form.get('channel') 49 | whisper_options = request.form.get('whisper') 50 | role_options = request.form.get("role") 51 | role_id = request.form.get("assign_role").split(',') 52 | delete_msg = request.form.get('delete_msg') 53 | delete_options = request.form.get("enable_delete") 54 | enable_msg = request.form.get("enable_message") 55 | if len(welcome_message) >= 2000 or welcome_message == "": 56 | flash("The welcome message need to be between 1-2000!", 'warning') 57 | else: 58 | try: 59 | delete_msg = int(delete_msg) 60 | except ValueError: 61 | flash('The delete message that you provided isn\'t an integer!', 'warning') 62 | return redirect(url_for('plugin_welcome', server_id=server_id)) 63 | db.hset('{}:Welcome:Message'.format(server_id), 'message', welcome_message) 64 | db.hset('{}:Welcome:Message'.format(server_id), 'channel', channel) 65 | db.hset('{}:Welcome:Message'.format(server_id), 'whisper', whisper_options) 66 | db.hset('{}:Welcome:Message'.format(server_id), 'delete_msg', delete_msg) 67 | db.hset('{}:Welcome:Message'.format(server_id), 'enable_delete', delete_options) 68 | db.hset('{}:Welcome:Message'.format(server_id), 'enable_message', enable_msg) 69 | flash('Settings updated!', 'success') 70 | db.hset('{}:Welcome:Message'.format(server_id), 'role', role_options) 71 | db.delete("{}:Welcome:Assign_role".format(server_id)) 72 | if len(role_id) > 0: 73 | db.sadd("{}:Welcome:Assign_Roles".format(server_id), *role_id) 74 | return dashboard(server_id=server_id) 75 | -------------------------------------------------------------------------------- /Site/templates/discourse/user_link_account.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% set csrf = csrf_token() %} 26 |
27 | {% include 'flash.html' %} 28 |
29 | 30 |

Discord and Discourse account link (Early Access?)

31 |
32 | This is where you will enter your discourse username, and Nurevam will check and get email and compare between your discord email. 33 |
34 |
35 | If your discord email and discourse email are different, it will not work of course, 36 |
37 |
38 | you will have few choice to do... such as changing one of them to same email 39 | or info your admin/owner to link up account via "!discourse link @mention username" 40 |
(Without quote of course, and change prefix if you are using custom.) 41 |
42 | where username is discourse username of your. 43 |
44 |
45 | Reason why Nurevam will be checking your both email is to confirm if you are indeed user. 46 | (This is to avoid people tricking Nurevam and get highest level to access hidden channel or what so ever reason...) 47 | 48 | All you need to do here is enter your own discourse username, and it will check and get email from there. 49 |
50 | 51 | {{template.text_box("discourse_user","Discourse Username",description = "Enter your discourse username here and Nurevam will check to confirm.",data = user_name)}} 52 | 53 | 54 | 55 |
56 |
57 |
58 |
59 | 60 | 61 | 62 | 63 | {% endblock %} 64 | -------------------------------------------------------------------------------- /Site/templates/full-page.html: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {{ title or 'Nurevam'}} 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 54 | 55 | {% block content %}{% endblock %} 56 | 57 | 59 | 60 | 61 | 62 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Bot/cogs/osu.py: -------------------------------------------------------------------------------- 1 | from osuapi import OsuApi, AHConnector 2 | from discord.ext import commands 3 | from .utils import utils 4 | import discord 5 | 6 | def is_enable(ctx): 7 | return utils.is_enable(ctx,"osu") 8 | 9 | class Osu(commands.Cog): 10 | def __init__(self,bot): 11 | self.bot = bot 12 | self.redis = bot.db.redis 13 | self.api = OsuApi(utils.secret["osu"], connector=AHConnector()) 14 | 15 | def cog_check(self,ctx): 16 | return utils.is_enable(ctx,"osu") 17 | 18 | async def get_account(self,ctx,author,isMention=False): 19 | setting = await self.redis.hget("Profile:{}".format(author.id),"osu") 20 | if setting is None and isMention: 21 | await self.bot.say(ctx,content="{} didn't register on yet! Tell him/her do it!".format(ctx.message.mentions[0].display_name)) 22 | elif setting is None: 23 | await self.bot.say(ctx,content="You need to enter a name! Or you can enter your own name in your profile at ") 24 | return setting 25 | 26 | @commands.command(pass_context=True,brief="Prints a stats of player's") 27 | async def osu(self,ctx,name=None): 28 | """ 29 | Links an osu! profile with additional info. 30 | Name: #rank 31 | Level: , PP: 32 | Country: #rank 33 | Total Play: 34 | Rank Score: 35 | Total Score: 36 | You can enter your username on the Nurevam site, so that Nurevam cant automatically link your profile. 37 | """ 38 | account = None 39 | 40 | if name is None: #Checking if Name is none, then it either user itself 41 | account = await self.get_account(ctx, ctx.message.author) 42 | elif bool(ctx.message.mentions): #mention someone 43 | account = await self.get_account(ctx,ctx.message.mentions[0],True) 44 | if account is None and name is None: return #if get_account return which mean user didnt link their osu username or name is also none... this name is here in case someone wrote name instead of themself. 45 | 46 | results = await self.api.get_user(account if account else name) 47 | if results: 48 | results = results[0] 49 | description = "**Level**: {0.level}, **PP**: {0.pp_raw}\n" \ 50 | "**Country**: {0.country} #{0.pp_country_rank}\n" \ 51 | "**Total Play**: {0.playcount}\n"\ 52 | "**Rank Score**: {0.ranked_score}\n" \ 53 | "**Total Score**: {0.total_score}\n".format(results) 54 | if ctx.message.channel.permissions_for(ctx.message.guild.me).embed_links: 55 | embed = discord.Embed() 56 | embed.colour = 0xFF66AA 57 | if account: 58 | user = ctx.message.mentions[0] if bool(ctx.message.mentions) else ctx.message.author 59 | embed.set_author(name=user, url="https://osu.ppy.sh/u/{}".format(results.user_id),icon_url=user.avatar_url) 60 | 61 | embed.set_thumbnail(url = "https://a.ppy.sh/{}".format(results.user_id)) 62 | embed.title = "**{0.username}: #{0.pp_rank}**".format(results) 63 | embed.url ="https://osu.ppy.sh/u/{}".format(results.user_id) 64 | embed.description = description 65 | await self.bot.say(ctx,embed = embed) 66 | else: 67 | msg = "{0.username}: #{0.pp_rank}\n".format(results)+description 68 | link = "\nhttps://a.ppy.sh/{0}".format(results.user_id) 69 | await self.bot.say(ctx, content = "```xl\n{}\n```{}".format(msg,link)) 70 | else: 71 | await self.bot.say(ctx,content = "I am sorry, but that name does not exist.") 72 | def setup(bot): 73 | bot.add_cog(Osu(bot)) 74 | -------------------------------------------------------------------------------- /Site/templates/custom commands/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 |

Custom Commands Disable

29 | {% include 'flash.html' %} 30 |
31 |
32 | 33 |
34 | People who have the right to make command can access here, I recommend bookmarking it so you can get there faster (Share link with creator role!) 35 |
36 | 37 | 38 |

Creator role

39 |
40 | Note: 0 means person who have this role can't create command, Other than that, above 0 will allow user who have that role can create x commands 41 | For now, {{limit}} is max for each person,(so meaning role will not add up total! keep that in mind), if wish to increase more than 10, complain to owner. 42 | If user have multi role, user will get max use from role that is higher than other 43 |
44 | 45 | {% for roles_half in role_max %} 46 |
47 | {% for role in roles_half if role.id != server.id %} 48 | 50 | 52 | {%endfor%} 53 |
54 | {%endfor%} 55 | 56 | 57 | 58 | 59 |
60 |
61 |
62 |
63 |
64 | 65 | 66 | {% endblock %} 67 | -------------------------------------------------------------------------------- /Site/templates/memes/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 |

Memes Disable

29 | {% include 'flash.html' %} 30 |
31 |
32 | 33 | 34 |
35 |
36 | Whoever have a role, can add memes they like. Make sure to include admin if wish to view it. 37 |
38 |
39 | People who have right to make memes can access here 40 |
41 | 66 |
67 | 68 |
69 |
70 |
71 |
72 |
73 | 74 | 75 | {% endblock %} 76 | -------------------------------------------------------------------------------- /Site/templates/discourse/category.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 |

Discourse Disable

29 | {% include 'flash.html' %} 30 |
31 | 32 |

Category

33 |
34 | Note Make sure Nurevam is able to speak on that channel, Default channel means Nurevam will only send that category to #{{default_channel}}.
None mean do not send any thread from this category to discord. 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | {% for cate_data in category %} 45 | 46 | {%if cate_data.sub == "true"%} 47 | 48 | {%else%} 49 | 50 | {%endif%} 51 | 63 | 64 | {%endfor%} 65 | 66 |
CategoryChannel
      └{{cate_data.name}}
{{cate_data.name}}
52 | 62 |
67 | 68 | 69 | 70 |
71 |
72 |
73 |
74 | 75 | {% endblock %} 76 | -------------------------------------------------------------------------------- /Site/templates/after_login.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 | 70 | {% endblock %} 71 | -------------------------------------------------------------------------------- /Site/templates/discourse/trust_role.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 | {% include 'flash.html' %} 29 |
30 | 31 |

Trust Level Grant Roles (Early Access?)

32 |
51 | 52 | {{template.typeahead("trust1","Trust level 1 Role",assign_role1,guild_roles,"role1","Role for people who have Trust level 1")}} 53 | {{template.typeahead("trust2","Trust level 2 Role",assign_role2,guild_roles,"role2","Role for people who have Trust level 2")}} 54 | {{template.typeahead("trust3","Trust level 3 Role",assign_role3,guild_roles,"role3","Role for people who have Trust level 3")}} 55 | {{template.typeahead("trust4","Trust level 4 Role",assign_role4,guild_roles,"role4","Role for people who have Trust level 4")}} 56 | 57 |
58 |
59 |
60 |
61 | 62 | 63 | 64 | 65 | {% endblock %} 66 | -------------------------------------------------------------------------------- /Bot/cogs/repl.py: -------------------------------------------------------------------------------- 1 | from contextlib import redirect_stdout 2 | from discord.ext import commands 3 | from .utils import utils 4 | import traceback 5 | import discord 6 | import inspect 7 | import io 8 | 9 | class REPL(commands.Cog): 10 | def __init__(self, bot): 11 | self.bot = bot 12 | self.sessions = set() 13 | 14 | def cleanup_code(self, content): 15 | """Automatically removes code blocks from the code.""" 16 | # remove ```py\n``` 17 | if content.startswith('```') and content.endswith('```'): 18 | return '\n'.join(content.split('\n')[1:-1]) 19 | 20 | # remove `foo` 21 | return content.strip('` \n') 22 | 23 | def get_syntax_error(self, e): 24 | return '```py\n{0.text}{1:>{0.offset}}\n{2}: {0}```'.format(e, '^', type(e).__name__) 25 | 26 | @commands.command(pass_context=True, hidden=True) 27 | @commands.check(utils.is_owner) 28 | async def repl(self, ctx): 29 | msg = ctx.message 30 | 31 | variables = { 32 | 'ctx': ctx, 33 | 'bot': self.bot, 34 | 'message': msg, 35 | 'guild': msg.guild, 36 | 'channel': msg.channel, 37 | 'author': msg.author, 38 | '_': None, 39 | 'redis':utils.redis 40 | } 41 | 42 | if msg.channel.id in self.sessions: 43 | await ctx.send('Already running a REPL session in this channel. Exit it with `quit`.') 44 | return 45 | 46 | self.sessions.add(msg.channel.id) 47 | await ctx.send('Enter code to execute or evaluate. `exit()` or `quit` to exit.') 48 | while True: 49 | response = await self.bot.wait_for("message", check=lambda m: m.content.startswith('`') and m.author == msg.author and m.channel == msg.channel) 50 | 51 | cleaned = self.cleanup_code(response.content) 52 | 53 | if cleaned in ('quit', 'exit', 'exit()'): 54 | await ctx.send('Exiting.') 55 | self.sessions.remove(msg.channel.id) 56 | return 57 | 58 | executor = exec 59 | if cleaned.count('\n') == 0: 60 | # single statement, potentially 'eval' 61 | try: 62 | code = compile(cleaned, '', 'eval') 63 | except SyntaxError: 64 | pass 65 | else: 66 | executor = eval 67 | 68 | if executor is exec: 69 | try: 70 | code = compile(cleaned, '', 'exec') 71 | except SyntaxError as e: 72 | await ctx.send(self.get_syntax_error(e)) 73 | continue 74 | 75 | variables['message'] = response 76 | 77 | fmt = None 78 | stdout = io.StringIO() 79 | 80 | try: 81 | with redirect_stdout(stdout): 82 | result = executor(code, variables) 83 | if inspect.isawaitable(result): 84 | result = await result 85 | except Exception as e: 86 | value = stdout.getvalue() 87 | fmt = '```py\n{}{}\n```'.format(value, traceback.format_exc()) 88 | else: 89 | value = stdout.getvalue() 90 | if result is not None: 91 | fmt = '```py\n{}{}\n```'.format(value, result) 92 | variables['last'] = result 93 | elif value: 94 | fmt = '```py\n{}\n```'.format(value) 95 | 96 | try: 97 | if fmt is not None: 98 | if len(fmt) > 2000: 99 | await ctx.send(await utils.send_hastebin(fmt)) 100 | else: 101 | await ctx.send(fmt) 102 | except discord.Forbidden: 103 | pass 104 | except discord.HTTPException as e: 105 | await ctx.send('Unexpected error: `{}`'.format(e)) 106 | 107 | def setup(bot): 108 | bot.add_cog(REPL(bot)) 109 | -------------------------------------------------------------------------------- /Bot/cogs/weather.py: -------------------------------------------------------------------------------- 1 | from discord.ext import commands 2 | from .utils import utils 3 | import datetime 4 | import aiohttp 5 | import discord 6 | 7 | class Weather(commands.Cog): #Allow to welcome new members who join guild. If it enable, will send them a message. 8 | def __init__(self,bot): 9 | self.bot = bot 10 | self.bot.say_edit = bot.say 11 | self.api = utils.secret["weather"] 12 | 13 | def cog_check(self,ctx): 14 | return utils.is_enable(ctx,"weather") 15 | 16 | @commands.command(brief="Allow to give you a info of weather realtive on that locate.") 17 | async def weather(self,ctx,*,locations:str="City,Country"): 18 | """ 19 | !weather city,country 20 | country is optional. 21 | When include country, add comma after city name 22 | Will show: 23 | Name 24 | Coordinates 25 | Weather Conditions 26 | Humidity: % 27 | Current Temperature: % 28 | Cloudiness: % 29 | Wind Speed: m/s 30 | sunrise: 00:00:00 utc / sunset: 00:00:00 utc 31 | """ 32 | if(locations == "City,Country"): return await self.bot.say(ctx,content = "You need to enter the city name") 33 | locate = locations.replace(" ","_") 34 | async with aiohttp.ClientSession() as session: 35 | link = "http://api.openweathermap.org/data/2.5/weather?q={}&appid={}&units=metric".format(locate,self.api) 36 | async with session.get(link) as resp: 37 | data = await resp.json() 38 | if data.get("cod") == '404': 39 | return await self.bot.say(ctx,content = "{}, did you type command correctly? such as `city,country`, " 40 | "note, it need comma for saying which country it is. You can just enter the city only.".format(data["message"])) 41 | icon = "https://openweathermap.org/img/w/{}.png".format(data["weather"][0]["icon"]) 42 | sunrise= datetime.datetime.fromtimestamp(data["sys"]["sunrise"]).strftime("%H:%M:%S") 43 | sunset= datetime.datetime.fromtimestamp(data["sys"]["sunset"]).strftime("%H:%M:%S") 44 | 45 | if ctx.message.channel.permissions_for(ctx.message.guild.me).embed_links: 46 | 47 | embed = discord.Embed() 48 | embed.title = "{0[name]}-{0[sys][country]}".format(data) 49 | embed.set_thumbnail(url = icon) 50 | embed.add_field(name = "Coordinates",value = "({0[coord][lat]},{0[coord][lon]})".format(data)) 51 | embed.add_field(name = "Conditions", value = "{0[weather][0][description]}".format(data)) 52 | embed.add_field(name = "Humidity", value = "{0[main][humidity]}%".format(data)) 53 | embed.add_field(name = "Current Temperature", value = "{0}°C/{1}°F".format(round(data["main"]["temp"]),round(data["main"]["temp"]*1.8+32))) 54 | embed.add_field(name = "Cloudiness", value = "{0[clouds][all]}".format(data)) 55 | embed.add_field(name = "Wind Speed", value = "{0[wind][speed]} m/s".format(data)) 56 | embed.set_footer(text = "Sunrise: {0} UTC and Sunset: {1} UTC".format(sunrise,sunset)) 57 | await self.bot.say(ctx,embed= embed) 58 | else: 59 | weather = "_**{0[name]}-{0[sys][country]}**_ -({0[coord][lat]},{0[coord][lon]})\n" \ 60 | "**Weather Conditions**: {0[weather][0][description]}\n" \ 61 | "**Humidity**: {0[main][humidity]}% \t **Current Temperature**: {1}°C/{2}°F\n" \ 62 | "**Cloudiness**: {0[clouds][all]}\t **Wind Speed**: {0[wind][speed]} m/s\n" \ 63 | "**Sunrise**: {3} UTC / **Sunset**: {4} UTC".format(data,round(data["main"]["temp"]), 64 | round(data["main"]["temp"]*1.8+32), 65 | sunrise,sunset) 66 | 67 | await self.bot.say(ctx,content = weather) 68 | def setup(bot): 69 | bot.add_cog(Weather(bot)) 70 | -------------------------------------------------------------------------------- /Site/templates/log/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 |

Log Disable

29 | {% include 'flash.html' %} 30 |
31 | 32 |
33 | 37 | 41 | 45 | 49 | 53 | 57 | 61 | 65 | 66 |
67 | {{ template.channel_list("channel","Channel for posting log",guild_channel,"Note,make sure Nurevam are able to speak on that channel!",log_channel)}} 68 | 69 |
70 |
71 |
72 |
73 | 74 | {% endblock %} 75 | -------------------------------------------------------------------------------- /Site/templates/level/theme.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 | {% include 'flash.html' %} 29 |
30 | 31 |
32 | 36 |
37 | {{template.text_box("pic_link","Picture Link","Link given, if it is just a empty box, then background will be default.",pic)}} 38 |
39 | 42 | 45 | 48 | 51 | 52 |
53 | 54 |
55 | Custom color setting, enter RGB/RGBA format(e.g 255,255,255 ) 56 |
57 | 58 | {{template.text_box("col_border","Border color","",color.get("border","255,255,255,96"))}} 59 | {{template.text_box("col_row","Row/Column color","",color.get("row","255,255,255,48"))}} 60 | {{template.text_box("col_outlier","Text outlier color","",color.get("outlier","255,255,255"))}} 61 | {{template.text_box("col_text","Text color","",color.get("text","0,0,0"))}} 62 | 63 | Ehum something went wrong... 64 |
65 | Please note this, This is just an example picture, size will be vary depends on name and other info. To have a best look, please active command in discord, where it will actually display name, level etc. 66 |
67 | 68 | 69 |
70 |
71 | 72 |
73 |
74 | {%endblock%} 75 | -------------------------------------------------------------------------------- /Site/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 22 | {% import 'template.html' as template %} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {{ title or 'Nurevam : the Discord bot !'}} 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 62 | {% block content %}{% endblock %} 63 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Site/templates/core.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | 29 | {% set csrf = csrf_token() %} 30 |
31 |

Core

32 | {% include 'flash.html' %} 33 |
34 |

Those are plugins that you can enable to allow message be auto delete. It will take 30 second for message delete if that command reply by bot from relative plugins that is enabled. 35 | P.S If you want bot delete user command as well, give bot a permission of manage message as well!

36 |
37 |
38 | {% for key in config_delete %} 39 | 43 | {% endfor %} 44 |
45 |
46 |
Help command Whisper, If it enable, it will PM you a help command instead of public.
47 |
48 |
49 | 53 |
54 |
55 |
56 | 57 | 58 | 59 |
60 |
61 |
Note! It will require a space after you set it, for example "Nure "<Space, otherwise, it will have to be "Nurerank",unless it is special character such as !,@,# which total make sense
62 |
Pro tips: Want a multi prefix? add comma then add new prefix you want! for example, "!,Nure ,Dank Memes " and you can do either !help or Dank Memes Help
63 |
Another pro tips! It will alway have @nurevam as well even you set other, so in case you forget your prefix!
64 |
Note, don't use comma as a prefix, it won't work. Trust me, been there and done that.
65 |
66 | 67 |
68 |
69 |
70 |
71 | 72 | {% endblock %} 73 | -------------------------------------------------------------------------------- /Site/templates/level/profile_level.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 | {% if is_owner %} 25 | {% if is_private %} 26 | Private 27 | {% else %} 28 | Public 29 | {% endif %} 30 | {% endif %} 31 | {% if is_private and not is_owner %} 32 |

Sorry, This page have set as private!

33 | {% else %} 34 |
35 |
36 |
37 |
38 | {% if icon ==None %} 39 |
40 | {%elif icon !=None %} 41 |
42 | {%endif%} 43 |

{{name}}

44 |
45 |
46 |
47 | {% if level !=None %} 48 |
49 |
50 |
51 |

Level: {{level["Level"]}}

52 |

{{level["XP"]}}/{{level["Next_XP"]}}XP [{{level["Total_XP"]}} total]
{{level["Percents"]}}%

53 |
54 |
55 |
56 |

Traits:{{level["Total_Traits_Points"]}}

57 |

Total Message:{{level["Total Message Count"]}}

58 |
59 |
60 |
61 | {%endif%} 62 | 63 |
64 |
65 | {% if data !=None %} 66 |
67 |
68 |
69 |

Command useds

70 |
71 | {% for info in data %} 72 |
73 |

{{info}}

74 |
75 | {% endfor %} 76 |
77 |
78 |
79 |
80 | {%endif%} 81 | 82 | 91 | {% endif %} 92 | {% endblock %} 93 | 94 | -------------------------------------------------------------------------------- /Site/templates/welcome/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 |

Welcome Disable

29 | {% include 'flash.html' %} 30 |
31 | 32 |
33 |
34 | 38 |
39 | {{ template.text_box("message","A Welcome message to newcomer!","Super Pro Tips: {user} is refer to new member's name,if you want a 40 | mention use 41 | {user_mention}, <{server} is server name of your.",message)}} 42 |
43 | 47 |
48 | {{ template.text_box("delete_msg","Custom time second to delete message","Given time to make bot delete message. Recommend not to this if you set Whisper Options.",delete_msg)}} 49 | 50 |
51 | 57 |
58 | {{ template.channel_list("channel","Welcome channel",guild_channel,"Note,make sure Nurevam are able to speak on that channel!",welcome_channel)}} 59 |
60 | 64 |
65 | {{template.typeahead("assign_role","Assign Role",assign_role,guild_roles,"assign_role","Role that can assign a member. Multiple role work as well.")}} 66 |
67 | 68 |
69 |
70 |
71 |
72 |
73 | 74 | 75 | {% endblock %} 76 | -------------------------------------------------------------------------------- /Bot/bot.py: -------------------------------------------------------------------------------- 1 | from discord.ext import commands 2 | from discord import errors 3 | from cogs.utils import utils 4 | import traceback 5 | import datetime 6 | import storage 7 | import discord 8 | import glob 9 | 10 | import helpformat 11 | 12 | description = '''Nurevam's Command List. 13 | To enable more commands, you must visit dashboard to enable certain plugins you want to run. 14 | If there is a problem with the prefix etc, please do @nurevam prefix to see what prefix you can do 15 | Any problem relating to Nurevam, please do contact owner Maverun (´・ω・`)#3333 16 | 17 | First └ mean it is commands under that plugin, and if there is one or more under commands, it is a sub command that can invoke by doing !parent subcommand such as !rank global 18 | ''' 19 | intents = discord.Intents.default() 20 | intents.members = True 21 | bot = commands.Bot(command_prefix=commands.when_mentioned_or("!"), 22 | help_command=helpformat.Custom_format(), 23 | description=description, 24 | pm_help = False, 25 | intents=intents, 26 | hidden = True,) 27 | 28 | bot.db= storage.Redis() 29 | redis = utils.redis 30 | 31 | def check_post(check): 32 | if check == "None": 33 | return None 34 | elif check == "on": 35 | return 30 36 | 37 | async def say(ctx,**kwargs): 38 | print("at say function",ctx,kwargs) 39 | check = await bot.db.redis.hget("{}:Config:Delete_MSG".format(ctx.message.guild.id),ctx.command.cog_name.lower()) 40 | return await ctx.send(**kwargs,delete_after=check_post(check)) 41 | 42 | bot.say=say 43 | 44 | @bot.event 45 | async def on_ready(): 46 | print('Logged in') 47 | print(bot.user.id) 48 | print('------') 49 | if not hasattr(bot, 'uptime'): 50 | bot.uptime = datetime.datetime.utcnow() 51 | bot.owner = (await bot.application_info()).owner 52 | bot.background = {} 53 | bot.id_discourse = 0 54 | bot.error_channel = bot.get_channel(823997727977111582) 55 | # bot.eng_lang = utils.read_lang("English") 56 | load_cogs() 57 | await bot.change_presence(activity = discord.Game("https://nurevam.site/")) 58 | 59 | async def command_checker(msg): 60 | try: 61 | if isinstance(msg.channel,discord.DMChannel): 62 | if "!reply" in msg.content: 63 | bot.command_prefix = commands.when_mentioned_or("!") 64 | return 65 | 66 | if bot.user.id == 181503794532581376: 67 | bot.command_prefix = commands.when_mentioned_or("$") 68 | bot.pm_help = False 69 | return 70 | 71 | cmd_prefix = await bot.db.redis.get("{}:Config:CMD_Prefix".format(msg.guild.id)) or "!" 72 | cmd_prefix = cmd_prefix.split(",") 73 | if '' in cmd_prefix: #check if "none-space" as a command, if true, return, in order to prevent any spam in case, lower chance of getting kick heh. 74 | return 75 | bot.command_prefix = commands.when_mentioned_or(*cmd_prefix) 76 | if "help" in msg.content: #changing setting for help, if guild owner want Help command to be via PM or to guild. 77 | if await bot.db.redis.get("{}:Config:Whisper".format(msg.guild.id)) == "on": 78 | bot.dm_help =True 79 | else: 80 | bot.dm_help =False 81 | except: 82 | pass 83 | 84 | @bot.event 85 | async def on_message(msg): #For help commands and custom prefix. 86 | await command_checker(msg) 87 | await bot.process_commands(msg) 88 | 89 | @bot.event 90 | async def on_message_edit(before,msg): #get command from edit message with same feature as on_message.. 91 | await command_checker(msg) 92 | await bot.process_commands(msg) 93 | 94 | def load_cogs(): 95 | raw_cogs = list_cogs() 96 | for cogs in raw_cogs: 97 | try: 98 | bot.load_extension(cogs) 99 | print (f"Load {cogs}") 100 | except Exception as e: 101 | utils.prRed(cogs) 102 | utils.prRed(e) 103 | 104 | def list_cogs(): 105 | cogs = glob.glob("cogs/*.py") 106 | clean = [] 107 | for c in cogs: 108 | c = c.replace("/", "\\") # Linux fix 109 | if "__init__" in c: 110 | continue 111 | clean.append("cogs." + c.split("\\")[1].replace(".py", "")) 112 | return clean 113 | 114 | @bot.event 115 | async def on_error(event,*args,**kwargs): 116 | print(event) 117 | print(args) 118 | print(kwargs) 119 | Current_Time = datetime.datetime.utcnow().strftime("%b/%d/%Y %H:%M:%S UTC") 120 | utils.prRed(Current_Time) 121 | utils.prRed("Error!") 122 | utils.prRed(traceback.format_exc()) 123 | error = '```py\n{}\n```'.format(traceback.format_exc()) 124 | try: 125 | # await bot.owner.send(f"```py\n{Current_Time}\nERROR!\n{error}```") 126 | await bot.error_channel.send(f"```py\n{Current_Time}\nERROR!\n{error}```") 127 | except: 128 | utils.prRed("Unable to send to owner/channel!") 129 | 130 | if __name__ == '__main__': 131 | bot.run(utils.secret["nurevam_token"]) 132 | -------------------------------------------------------------------------------- /Site/templates/template.html: -------------------------------------------------------------------------------- 1 | 21 | {% set csrf = csrf_token() %} 22 | 23 | {% macro text_box(html_name,name,description = "",data = "") %} 24 | 25 |
26 | 27 | 28 | 29 |
30 | {% if description != ""%} 31 |
32 | {{description|safe}} 33 |
34 | {%endif%} 35 | 36 | {% endmacro %} 37 | 38 | {% macro typeahead(html_name,name,data_list,guild_data,var_key,description = "",key_name = "name") %} 39 | 40 | 41 |
42 |
43 | {% if description != ""%} 44 | {{description|safe}} 45 | {% else %} 46 | 47 | {%endif%} 48 |
49 | 77 | 78 | 79 | {% endmacro %} 80 | 81 | 82 | {% macro channel_list(html_name,title,guild_channel,description = "",data = "") %} 83 | 84 | {% if description != ""%} 85 |
86 | 87 | 94 |
95 | {{description|safe}} 96 |
97 |
98 | 99 | {%endif%} 100 | 101 | {% endmacro %} 102 | 103 | {% macro select_list(html_name,title,data_list,description = "",data = "") %} 104 | 105 | {% if description != ""%} 106 |
107 | 108 | 115 | {% if description != ""%} 116 |
117 | {{description|safe}} 118 |
119 | {%endif%} 120 | 121 |
122 | 123 | {%endif%} 124 | 125 | {% endmacro %} 126 | -------------------------------------------------------------------------------- /Site/templates/mod/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 |

Mod Disable

29 | {% include 'flash.html' %} 30 |
31 |
32 | 33 | 34 | 35 |
36 |
37 | Admin role that can do to mod command 38 |
39 | 62 | 63 | 64 |
65 |
66 | Mute people via !mute @person or !unmute @person. People with admin role can use it ^^^ 67 |
68 | 91 | 92 | 93 | 94 |
95 | 96 |
97 |
98 |
99 |
100 |
101 | 102 | 103 | {% endblock %} 104 | -------------------------------------------------------------------------------- /Site/templates/level/index.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 |
24 |
25 | {% include 'sidebar.html' %} 26 | {% set csrf = csrf_token() %} 27 |
28 |

Levels Disable

29 | {% include 'flash.html' %} 30 |
31 |
32 | 33 | {{template.text_box("announcement","Level UP announcement",data =config["announce_message"])}} 34 |
35 | 39 | 43 |
44 | {{template.text_box("cooldown","!rank command cooldown","In order to avoid people 45 | flooding the !rank command, you can set a cooldown in 46 | seconds.",cooldown if cooldown else 0)}} 47 | 48 |
49 | Tips: {player} refers to the player, {level} to his/her 50 | level.

51 | Commands: !rank !levels

52 | Leaderboard: HERE ! 54 |
55 | {{template.typeahead("banned_members","Banned Member",banned_members,guild_members,"banned_members","These member won't get xp.","username")}} 56 | {{template.typeahead("banned_roles","Banned Role",banned_roles,guild_roles,"banned_roles","These roles won't get xp.")}} 57 | {{template.typeahead("banned_channels","Banned Channels",banned_channels,guild_channels,"banned_channels","These channel that user speak won't get xp.")}} 58 | 59 | 60 |
61 | Picture of Table: Instead of embeds for table commands, you can do custom picture right HERE! I recommend update first before clicking it. 63 |
64 | 65 |

Roles Rewards

66 |
67 | Note: 0 mean no reward. Please make sure Nurevam have role that have manage role permission and above most of role (due to hierarchy) 68 | Also, Nurevam are able to remove role(I think..). 69 |
70 | 71 | {% for reward_roles_half in reward_roles %} 72 |
73 | {% for role in reward_roles_half if role.id != server.id %} 74 | 76 | 78 | {%endfor%} 79 |
80 | {%endfor%} 81 | 82 |
83 |
84 |
85 |
86 |
87 | 88 | {% endblock %} 89 | -------------------------------------------------------------------------------- /Site/templates/memes/memes.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'full-page.html' %} 22 | {% block content %} 23 |
24 |
25 |
26 | {% set csrf = csrf_token() %} 27 |
28 | {% include 'flash.html' %} 29 |

Memes add

30 |
31 |
Provide a name and link for a custom memes. Nurevam do not store picture, so you will need to host images somewhere such as imgur
32 |
If you are gonna provide a picture with white background, you are gonna have a bad time...
33 |
Note: Depends on size of the picture, how long message are, those may mess up memes around.
34 |
35 |
36 |
37 | 38 | 39 | 42 |
43 |
44 |
45 |
46 | 47 | 48 | 51 |
52 |
53 |
54 | Add 55 |
56 |
57 |
58 |
59 | {% if data_memes %} 60 |

Edit Memes

61 |
62 |
63 |
64 | {% for memes in data_memes %} 65 |
66 |
67 |
68 |
69 |
70 | 71 | 72 | 75 |
76 |
77 |
78 |
79 | 80 | 81 | 84 |
85 |
86 |
87 | Update 88 | Delete 90 |
91 |
92 |
93 |
94 | {% endfor %} 95 |
96 |
97 |
98 | {% endif %} 99 |
100 |
101 | 109 | 110 | {% endblock %} 111 | -------------------------------------------------------------------------------- /Site/templates/antiraid/index.html: -------------------------------------------------------------------------------- 1 | 21 | 22 | {% extends 'dash_base.html' %} 23 | {% block dash_content %} 24 |
25 |
26 | {% include 'sidebar.html' %} 27 | {% set csrf = csrf_token() %} 28 |
29 |

Anti Raid Disable

30 | {% include 'flash.html' %} 31 |
32 | 33 |
34 | Please note, this is in beta, I am unable to test it myself as it would require more people for the overall features. If something doesn't work, please check the settings here, if it is looking fine, please report it to me in the Nurevam server or contact me @Maverun (´・ω・`)#3333... 35 | Should something happen that you are not expecting, and you aren't happy with the result, I'm very sorry for this, as this is beta with a lack of testing. 36 | 37 | 38 | Please do note that this plugin is only monitoring people who join this server for a day. 39 | Which mean as long as they join server within 24 hours, this plugin is watching them over. 40 | (Discord invite link might apply to all member regardless of 24 hours.) 41 | 42 | It will update every min or so in bot, so please wait for it take effect. 43 |
44 |

Config actions

45 |
46 |
47 | {{template.select_list("invite_link","Discord Invite Link",option_data,"If person posts a discord invite link that is not this server, it will take action",config['invite_link'])}} 48 |
49 |
50 | {{template.select_list("any_link","Any Link",option_data,"If person posts a link right after it join within x time, it will take action (such as sex bot etc)",config['any_link'])}} 51 |
52 |
53 | {{template.select_list("spam_msg","Spamming similar messages",option_data,"If person spams a similar message x times within x sec, it will take action (look below)",config['spam_msg'])}} 54 |
55 |
56 | {{template.select_list("member_age","Age of account",option_data,"If person joins this server and their account is younger then x seconds old (for example 10 sec old), it will take an action",config['member_age'])}} 57 |
58 |
59 | {{template.select_list("multi_people","Mutliple people joining at a same time",option_data,"If there is multiple people joining this server within x sec, it will take action on all of those members",config['multi_people'])}} 60 |
61 |
62 | {{template.select_list("multi_ping","Massive Ping",option_data,"If there is a massive mention such as mention more than 20 people in a message (will also delete said message)",config['multi_ping'])}} 63 |
64 | 65 |
66 |

Settings for each config

67 |
68 |
69 |
70 | {{template.text_box("any_link_time","Any link time","If a user posts any link (Not invite link) within x seconds from join, action taken. Note this is second(s)",config['any_link_time'])}} 71 |
72 |
73 | {{template.text_box("member_age_time","New user's account age","If user is below x age, it will take an action to this user. Note: number are in second(s)",config['member_age_time'])}} 74 |
75 | 76 |
77 | {{template.text_box("multi_people_limit","Total of multiple people joining at once","Maximum members that can join before the bot takes action",config['multi_people_limit'])}} 78 |
79 | 80 |
81 | {{template.text_box("multi_people_time","Total of multiple people joining timeout","Check how many members join within x seconds",config['multi_people_time'])}} 82 |
83 | 84 |
85 | {{template.text_box("spam_msg_count","Spamming similar message count","This is checking how many time has this same user spams a similar message",config['spam_msg_count'])}} 86 |
87 |
88 | {{template.text_box("spam_msg_time","Spamming similar message timer","If a user spams x amount of similar message within time, it will take an action",config['spam_msg_time'])}} 89 |
90 |
91 | {{template.text_box("spam_msg_percent","Similarity checking percent","This is checking how close is message to each other from 1 to 100. Such as 'meat!', 'meAt!' etc. Recommend: 90 ",config['spam_msg_percent'])}} 92 |
93 |
94 | {{template.text_box("multi_ping_limit","Massive ping limit","If user pings more then x times in one message, It will take an action",config['multi_ping_limit'])}} 95 |
96 | 97 |
98 | {{template.typeahead("mute_roles","Mute Role",mute_roles,guild_roles,"mute_roles","If you select any role grant during Config Action, this is what will give role to people")}} 99 | 100 |
101 |
102 | 103 |
104 |
105 |
106 |
107 |
108 | 109 | {% endblock %} 110 | -------------------------------------------------------------------------------- /Site/static/js/mention.js: -------------------------------------------------------------------------------- 1 | /*jslint forin: true */ 2 | 3 | ;(function($) { 4 | $.fn.extend({ 5 | mention: function(options) { 6 | this.opts = { 7 | users: [], 8 | delimiter: '@', 9 | sensitive: true, 10 | emptyQuery: false, 11 | queryBy: ['name', 'username'], 12 | typeaheadOpts: {} 13 | }; 14 | 15 | var settings = $.extend({}, this.opts, options), 16 | _checkDependencies = function() { 17 | if (typeof $ == 'undefined') { 18 | throw new Error("jQuery is Required"); 19 | } 20 | else { 21 | if (typeof $.fn.typeahead == 'undefined') { 22 | throw new Error("Typeahead is Required"); 23 | } 24 | } 25 | return true; 26 | }, 27 | _extractCurrentQuery = function(query, caratPos) { 28 | var i; 29 | for (i = caratPos; i >= 0; i--) { 30 | if (query[i] == settings.delimiter) { 31 | break; 32 | } 33 | } 34 | return query.substring(i, caratPos); 35 | }, 36 | _matcher = function(itemProps) { 37 | var i; 38 | 39 | if(settings.emptyQuery){ 40 | var q = (this.query.toLowerCase()), 41 | caratPos = this.$element[0].selectionStart, 42 | lastChar = q.slice(caratPos-1,caratPos); 43 | if(lastChar==settings.delimiter){ 44 | return true; 45 | } 46 | } 47 | 48 | for (i in settings.queryBy) { 49 | if (itemProps[settings.queryBy[i]]) { 50 | var item = itemProps[settings.queryBy[i]].toLowerCase(), 51 | usernames = (this.query.toLowerCase()).match(new RegExp(settings.delimiter + '\\w+', "g")), 52 | j; 53 | if ( !! usernames) { 54 | for (j = 0; j < usernames.length; j++) { 55 | var username = (usernames[j].substring(1)).toLowerCase(), 56 | re = new RegExp(settings.delimiter + item, "g"), 57 | used = ((this.query.toLowerCase()).match(re)); 58 | 59 | if (item.indexOf(username) != -1 && used === null) { 60 | return true; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | }, 67 | _updater = function(item) { 68 | var data = this.query, 69 | caratPos = this.$element[0].selectionStart, 70 | i; 71 | 72 | for (i = caratPos; i >= 0; i--) { 73 | if (data[i] == settings.delimiter) { 74 | break; 75 | } 76 | } 77 | var replace = data.substring(i, caratPos), 78 | textBefore = data.substring(0, i), 79 | textAfter = data.substring(caratPos), 80 | data = textBefore + settings.delimiter + item + textAfter; 81 | 82 | this.tempQuery = data; 83 | 84 | return data; 85 | }, 86 | _sorter = function(items) { 87 | if (items.length && settings.sensitive) { 88 | var currentUser = _extractCurrentQuery(this.query, this.$element[0].selectionStart).substring(1), 89 | i, len = items.length, 90 | priorities = { 91 | highest: [], 92 | high: [], 93 | med: [], 94 | low: [] 95 | }, finals = []; 96 | if (currentUser.length == 1) { 97 | for (i = 0; i < len; i++) { 98 | var currentRes = items[i]; 99 | 100 | if ((currentRes.username[0] == currentUser)) { 101 | priorities.highest.push(currentRes); 102 | } 103 | else if ((currentRes.username[0].toLowerCase() == currentUser.toLowerCase())) { 104 | priorities.high.push(currentRes); 105 | } 106 | else if (currentRes.username.indexOf(currentUser) != -1) { 107 | priorities.med.push(currentRes); 108 | } 109 | else { 110 | priorities.low.push(currentRes); 111 | } 112 | } 113 | for (i in priorities) { 114 | var j; 115 | for (j in priorities[i]) { 116 | finals.push(priorities[i][j]); 117 | } 118 | } 119 | return finals; 120 | } 121 | } 122 | return items; 123 | }, 124 | _render = function(items) { 125 | var that = this; 126 | items = $(items).map(function(i, item) { 127 | 128 | i = $(that.options.item).attr('data-value', item.username); 129 | 130 | var _linkHtml = $('
'); 131 | 132 | if (item.image) { 133 | _linkHtml.append(''); 134 | } 135 | if (item.name) { 136 | _linkHtml.append('' + item.name + ''); 137 | } 138 | if (item.username) { 139 | _linkHtml.append(' ' + settings.delimiter + item.username + ''); 140 | } 141 | 142 | i.find('a').html(that.highlighter(_linkHtml.html())); 143 | return i[0]; 144 | }); 145 | 146 | items.first().addClass('active'); 147 | this.$menu.html(items); 148 | return this; 149 | }; 150 | 151 | $.fn.typeahead.Constructor.prototype.render = _render; 152 | 153 | return this.each(function() { 154 | var _this = $(this); 155 | if (_checkDependencies()) { 156 | _this.typeahead($.extend({ 157 | source: settings.users, 158 | matcher: _matcher, 159 | updater: _updater, 160 | sorter: _sorter 161 | }, settings.typeaheadOpts)); 162 | } 163 | }); 164 | } 165 | }); 166 | })(jQuery); -------------------------------------------------------------------------------- /Site/templates/level/levels.html: -------------------------------------------------------------------------------- 1 | 21 | {% extends 'dash_base.html' %} 22 | {% block dash_content %} 23 | 24 | {% if css_theme %} 25 | 26 | {% endif %} 27 | 28 |
29 |
30 |
31 |

How it works

32 |
33 |
34 | Each time you post a message you get a random number of XP between 5 and 10.

35 | To avoid flood, you can only gain xp once per minute.

36 | In the server, you can type !rank to get your rank and your level. 37 |
38 |
39 |
40 |
41 |

Stats

42 |
43 |
44 | Total Rank: {{stats['total_member']}}

45 | Total EXP: {{stats['total_exp']}} 46 |
47 |
48 |
49 |
50 |

Role Rewards

51 |
52 |
53 | {%if reward_roles%} 54 |
55 | {% for role in reward_roles if role.id != server.id %} 56 |
57 |

{{role.name}}

58 |

-Level:{{role.level}}

59 |
60 | {%endfor%} 61 |
62 | {%else%} 63 |

There are no role rewards!

64 | {%endif%} 65 |
66 |
67 |
68 |
69 |

Leaderboard 70 | {% if is_admin %} 71 | RESET ALL 72 | {% if is_private %} 73 | Private from Leaderboard 74 | {% else %} 75 | Public from Leaderboard 76 | {% endif %} 77 | CSS edit 78 | {% endif %} 79 |

80 |
81 | {% for player in players %} 82 |
83 |
84 |
85 |

#{{loop.index}}

86 |
87 | 94 |
95 |

{{player['Name']}} #{{player['Discriminator']}}

96 |
97 |
98 |
{{player['XP']}} / {{player['Next_XP']}} XP [{{player['Total_XP']}} total]
99 |
100 |
101 |
102 |
103 |
104 |

Level {{player['Level']}} 105 | {% if is_admin %} 106 | reset 107 | {% endif %} 108 |

109 |
110 |
111 |
112 | {% endfor %} 113 |
114 |
115 | 116 |
117 |
118 | 141 | 142 | {% endblock %} 143 | -------------------------------------------------------------------------------- /Bot/cogs/commands.py: -------------------------------------------------------------------------------- 1 | from urllib.parse import urlparse 2 | from discord.ext import commands 3 | from .utils import utils 4 | import collections 5 | import traceback 6 | import functools 7 | import discord 8 | import inspect 9 | import logging 10 | import asyncio 11 | import datetime 12 | 13 | log = logging.getLogger(__name__) 14 | 15 | """ 16 | Credit to Danny(Rapptz) for example of custom commands 17 | It was based of his and improve from there with a lot of changes to my like. 18 | I believe this cogs is full of hack. 19 | """ 20 | 21 | 22 | class CreateCustom: 23 | def __init__(self,**kwargs): 24 | self.name = kwargs.get('name') 25 | self.content = kwargs.get('content') 26 | self.brief= kwargs.get('brief') 27 | self.guild_id= kwargs.get('guild_id') 28 | 29 | 30 | async def run_command(cmd,o,ctx,*args:str): 31 | """ 32 | Custom Command 33 | """ 34 | 35 | """ 36 | Args: 37 | cmd: CreateCustom Obj 38 | o: Nothing 39 | ctx: ctx 40 | *args: any remain message from user 41 | """ 42 | args = list(args) 43 | #ignore obj 44 | 45 | if(bool(urlparse(cmd.content).netloc)): 46 | temp = cmd.content.find(".", int(len(cmd.content)/2)) 47 | temp = cmd.content[temp:] 48 | picture = False 49 | for x in ["png","gif","jpg","bmp","jpeg"]: 50 | if x in temp.lower(): 51 | picture = True 52 | break 53 | if picture: 54 | embed = discord.Embed() 55 | embed.set_image(url = cmd.content) 56 | return await ctx.send(embed = embed) 57 | msg = ctx.message 58 | name = "" 59 | mention = "" 60 | #a bad way to fix it, way i know, sorry. 61 | cmd.content = cmd.content.replace("\\t","\t").replace("\\n","\n") 62 | if msg.mentions: #putting mention in 63 | ment = msg.mentions 64 | for i in range(len(ment)): 65 | x = ment.pop(0) 66 | blank = " " 67 | if len(ment) >1: 68 | blank = "," 69 | name += x.name + blank 70 | mention += x.mention + blank 71 | if args: 72 | log.debug("Cleaning out mentions") 73 | try: 74 | for l in range(len(args)): 75 | args.pop(args.index(x.mention)) #when there is dupe mention 76 | except Exception as e: 77 | log.debug(e) 78 | pass 79 | content = cmd.content.format(cmduser = msg.author.name,cmdmention = msg.author.mention, 80 | user = name, mention = mention,msg = " ".join(args)) 81 | await ctx.send(content[:2000]) #sorry folk, you wont make it past 2k! 82 | 83 | class CustomCmd(commands.Command): 84 | def __init__(self,func,**kwargs): 85 | self._entries = {} 86 | self.module = None 87 | super().__init__(func,**kwargs) 88 | self.name = kwargs.get("name",self.name) 89 | self.brief = kwargs.get("brief",self.brief) 90 | self.params = collections.OrderedDict() 91 | self.params["cog"] = self.cog # These are for help command to ignore errors by user. 92 | self.params["ctx"] = "nothing"# These are for help command to ignore errors by user. 93 | 94 | async def callback(self): 95 | pass #ignore any problem and JUST CARRY ON. 96 | 97 | async def invoke(self, ctx): 98 | server = ctx.message.guild 99 | if server is not None: 100 | log.debug("Invoke command: {} , guild ID {}".format(ctx.command.name,server.id)) 101 | entry = self._entries.get(server.id) 102 | if entry is None: 103 | return 104 | 105 | # update the callback called 106 | self.callback = functools.partial(run_command, entry) 107 | self.params = inspect.signature(self.callback).parameters 108 | 109 | await super().invoke(ctx) 110 | 111 | 112 | async def can_run(self,ctx): 113 | server = ctx.message.guild 114 | if server is not None: 115 | log.debug("checking conditions, {} , {}".format(ctx.command.name,server.id)) 116 | get_entry = self._entries.get(server.id) 117 | if get_entry: #to make brief for that server, totally hacky way? 118 | try: 119 | ctx.bot.get_command(get_entry.name).brief = get_entry.brief or "" 120 | except: #if user didn't enter brief in. 121 | pass 122 | return bool(get_entry) 123 | 124 | 125 | class Custom_Commands(commands.Cog, name = "Custom Commands"): 126 | """ 127 | An unique custom commands for your server! 128 | """ 129 | def __init__(self,bot): 130 | self.bot = bot 131 | self.redis = bot.db.redis 132 | self.starter = True 133 | self.bg = utils.Background("customcmd",60,50,self.timer,log) 134 | self.bot.background.update({"customcmd":self.bg}) 135 | self.bg.start() 136 | 137 | def cog_unload(self): 138 | self.bg.stop() 139 | 140 | def cog_check(self,ctx): 141 | return utils.is_enable(ctx,"custom commands") 142 | 143 | async def timer(self): 144 | try: 145 | for guild in list(self.bot.guilds): 146 | log.debug(guild) 147 | if await self.redis.hget("{}:Config:Cogs".format(guild.id),"custom commands") == "on": 148 | list_name = await self.redis.smembers("{}:Customcmd:update_delete".format(guild.id)) 149 | log.debug(list_name) 150 | if list_name: 151 | for name in list_name: #if it edit or delete, either way remove them, we will do fresh update 152 | cmd = self.bot.get_command(name) 153 | print(cmd) 154 | if cmd: 155 | #Set None.. for some reason doesn't exist? 156 | cmd._entries.pop(guild.id,None) 157 | await self.redis.delete("{}:Customcmd:update_delete".format(guild.id)) 158 | if await self.redis.get("{}:Customcmd:update".format(guild.id)) or list_name or self.starter is True: #Which mean there is update 159 | log.debug("adding commands") 160 | cmd_content = await self.redis.hgetall("{}:Customcmd:content".format(guild.id)) 161 | cmd_brief = await self.redis.hgetall("{}:Customcmd:brief".format(guild.id)) 162 | log.debug("commands contents: {}".format(cmd_content)) 163 | for name,content in cmd_content.items(): 164 | log.debug("name {} : content: {}".format(name,content)) 165 | brief = cmd_brief[name] 166 | entry = CreateCustom(name=name.lower(), content=content, brief = brief,guild_id=guild.id) 167 | self.create_command(entry) 168 | await self.redis.delete("{}:Customcmd:update".format(guild.id)) 169 | self.starter = False 170 | 171 | except asyncio.CancelledError: 172 | return utils.prRed("Asyncio Cancelled Error") 173 | except Exception as e: 174 | utils.prRed(e) 175 | utils.prRed(traceback.format_exc()) 176 | 177 | def create_command(self,cmd): 178 | cmd_exit = self.bot.get_command(cmd.name) 179 | log.debug(cmd_exit) 180 | if cmd_exit is None: #checking if we have exist command 181 | command = self.bot.command(name = cmd.name, brief = cmd.brief,cls = CustomCmd)(run_command) #Decorator 182 | command.cog = self #adding cog to command so it can format in help. 183 | command._entries[cmd.guild_id] = cmd 184 | elif isinstance(cmd_exit,CustomCmd): 185 | log.debug("command already exist") 186 | cmd_exit._entries[cmd.guild_id] = cmd 187 | 188 | def setup(bot): 189 | bot.add_cog(Custom_Commands(bot)) 190 | -------------------------------------------------------------------------------- /Bot/cogs/utils/utils.py: -------------------------------------------------------------------------------- 1 | import redis as rdb 2 | import traceback 3 | import datetime 4 | import platform 5 | import aiohttp 6 | import asyncio 7 | import json 8 | 9 | #############Color for Terminal############################### 10 | #Whole line, and easier to debug 11 | def prRed(prt): print("\033[91m{}\033[00m".format(prt)) 12 | def prGreen(prt): print("\033[92m{}\033[00m".format(prt)) 13 | def prYellow(prt): print("\033[93m{}\033[00m".format(prt)) 14 | def prLightPurple(prt): print("\033[94m{}\033[00m".format(prt)) 15 | def prPurple(prt): print("\033[95m{}\033[00m".format(prt)) 16 | def prCyan(prt): print("\033[96m{}\033[00m".format(prt)) 17 | def prLightGray(prt): print("\033[97m{}\033[00m".format(prt)) 18 | def prBlack(prt): print("\033[98m{}\033[00m".format(prt)) 19 | ############################################################### 20 | 21 | #read files and save it to secret 22 | with open ("../secret.json","r",encoding = "utf8") as f: 23 | secret = json.load(f) 24 | 25 | ###########Connection Line#################### 26 | redis = rdb.Redis(host=secret["Redis"], decode_responses=True) 27 | 28 | def is_owner(ctx): #Checking if you are owner of bot 29 | return ctx.message.author.id == 105853969175212032 30 | 31 | ############Checking if cogs for that guild is enable or disable########## 32 | def is_enable(ctx,cog): 33 | try: 34 | return redis.hget("{}:Config:Cogs".format(ctx.message.guild.id),cog) == "on" 35 | except: 36 | return False 37 | 38 | ######################Checking if Role is able###################################### 39 | def check_roles(ctx,cog,get_role): #Server ID then which plugin, and Roles with set 40 | try: 41 | db_role= redis.smembers("{}:{}:{}".format(ctx.message.guild.id,cog,get_role)) 42 | print("Roles: ",db_role) 43 | author_roles= [role.id for role in ctx.message.author.roles] 44 | print(author_roles) 45 | for role in db_role: 46 | print(role) 47 | if int(role) in author_roles: 48 | return True 49 | return False 50 | except Exception as e: 51 | prRed("ERROR\n{}".format(e)) 52 | return False 53 | 54 | async def send_hastebin(info): 55 | async with aiohttp.ClientSession() as session: 56 | async with session.post("https://hastebin.com/documents",data = str(info)) as resp: 57 | if resp.status == 200: 58 | return "https://hastebin.com/{}.py".format((await resp.json())["key"]) 59 | 60 | async def input(bot,ctx,msg,check): 61 | """ 62 | 63 | Args: 64 | ctx: discord Context 65 | msg: Message to send to users 66 | check: conditions accept from user. 67 | 68 | Returns: return message object from user's 69 | 70 | """ 71 | asking = await ctx.send(msg) #sending message to ask user something 72 | try: 73 | answer = await bot.wait_for("message", timeout=15, check=check) 74 | await answer.delete() 75 | except asyncio.TimeoutError: # timeout error 76 | await asking.delete() 77 | await ctx.send(content="You took too long, please try again!",delete_after = 15) 78 | return None 79 | except: 80 | pass 81 | await asking.delete() # bot delete it own msg. 82 | return answer 83 | 84 | class Background: 85 | """ 86 | Background, allow to run auto background task easily without worry. 87 | """ 88 | 89 | current = datetime.datetime.utcnow() #datetime obj 90 | 91 | def __init__(self,name,max_time,sleep_time,function,log): 92 | self.name = name 93 | self.max_time = max_time 94 | self.sleep_time = sleep_time 95 | self.function = function #function to call 96 | self.log = log 97 | self.current = datetime.datetime.utcnow() 98 | 99 | def start(self): #to start function run 100 | loop = asyncio.get_event_loop() 101 | self.loop_timer = loop.create_task(self.timer()) 102 | prLightPurple("Starting {} loop".format(self.name)) 103 | 104 | def stop(self): 105 | self.loop_timer.cancel() 106 | prLightPurple("Stopping {} loop".format(self.name)) 107 | 108 | 109 | async def timer(self): 110 | try: 111 | while True: 112 | self.current = datetime.datetime.utcnow() 113 | self.log.debug(self.current) 114 | self.log.debug("Calling event") 115 | await self.function() 116 | self.log.debug("Enter sleep mode") 117 | await asyncio.sleep(self.sleep_time) 118 | except asyncio.CancelledError: 119 | return prRed("Asyncio Cancelled Error") 120 | except Exception as e: 121 | print(e) 122 | prRed(traceback.format_exc()) 123 | 124 | class Embed_page: 125 | """ 126 | Embed page, with reaction to go next or now (or other reaction for certain feature) 127 | """ 128 | 129 | def __init__(self,bot,embed_list,**kwargs): 130 | self.bot = bot 131 | self.embed_page = embed_list #expecting list of embed 132 | self.max_page = kwargs.get("max_page",len(embed_list)) 133 | self.page = kwargs.get("page",0) #current page, default is 0 134 | self.alt_edit = kwargs.get("alt_edit") #if wish to edit message AFTER return function that is not belong here 135 | self.original_msg = kwargs.get("original_msg") #^ 136 | #this is array with emotion:function, so we can have each reaction for certain function. Reason for array is order 137 | self.reaction = kwargs.get("reaction", [[u"\u2B05",self.back_page],[u"\u27A1",self.continue_page]]) 138 | 139 | 140 | def back_page(self,*args): 141 | self.page -= 1 142 | if self.page -1 <= 0: 143 | self.page = 0 #dont change it 144 | return self.page 145 | 146 | def continue_page(self,*args): 147 | self.page += 1 148 | if self.page > self.max_page - 1: 149 | self.page = self.max_page - 1 150 | return self.page 151 | 152 | def get_page(self): 153 | return self.embed_page[self.page] 154 | 155 | async def wait_for_react(self,check,timeout): 156 | try: 157 | reaction, user = await self.bot.wait_for("reaction_add", timeout = timeout, check = check) 158 | except asyncio.TimeoutError: 159 | return None,None 160 | else: 161 | return reaction,user 162 | 163 | async def start(self,channel,check,timeout = 60,is_async = False,extra = []): 164 | """ 165 | 166 | Args: 167 | channel: discord.channel. A destination to send message. 168 | check : checking permission for this. 169 | timeout: timeout for message to run if no one rect. Default 60 second 170 | 171 | It will send message or edit message if original_msg exist. To get that, you will need to pass self.alt_edit True and rerun this template. 172 | Run iterate of self.reaction for adding rect into it 173 | Then finally run endless loops waiting for message etc 174 | """ 175 | if self.original_msg: 176 | await self.original_msg.edit(embed = self.get_page()) 177 | self.message = self.original_msg 178 | else: 179 | self.message = await channel.send(embed = self.get_page()) 180 | 181 | for rect in self.reaction: 182 | await self.message.add_reaction(rect[0]) 183 | 184 | while True: 185 | react,user = await self.wait_for_react(check,timeout) 186 | #If react is none, it mean that it had reach timeout and user didn't react. 187 | if react is None: 188 | return await self.message.clear_reactions() 189 | #remove user's message 190 | try: 191 | 192 | await self.message.remove_reaction(react.emoji,user) 193 | except: #if bot does not have permission for it. Oh well. Hard time for user. 194 | pass 195 | 196 | #now we will find reaction it used and then run function of that. 197 | #once we do that, we will delete that reaction. 198 | 199 | for item in self.reaction: 200 | if item[0] == react.emoji: #if it equal then we can call function 201 | if is_async: 202 | if self.alt_edit: 203 | await item[1](react,user,self.message,*extra) 204 | else: 205 | await item[1](react,user,*extra) 206 | else: 207 | if self.alt_edit: 208 | item[1](react,user,self.message,*extra) 209 | else: 210 | item[1](react,user,*extra) 211 | break 212 | 213 | #now we will update message again 214 | await self.message.edit(embed = self.get_page()) 215 | 216 | --------------------------------------------------------------------------------