10 skills found
Defxult / ReactionmenuA library to create a discord.py 2.0+ paginator (reaction menu/buttons menu). Supports pagination with buttons, reactions, and category selection using selects.
IDjinn / Discord.js CollectorLibrary to easily create message collector, reactions collector and reactions role on discord.js v12, with customization ways.
Wallace-Best / Best<!DOCTYPE html>Wallace-Best <html lang="en-us"> <head> <link rel="node" href="//a.wallace-bestcdn.com/1391808583/img/favicon16-32.ico" type="image/vnd.microsoft.icon"> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="Content-Language" content="en-us"> <meta name="keywords" content="Wallace Best, wallace-best.com, comments, blog, blogs, discussion"> <meta name="description" content="Wallace Best's Network is a global comment system that improves discussion on websites and connects conversations across the web."> <meta name="world" value="notranslate" /> <title> WB Admin | Sign-in </title> <script type="text/javascript" charset="utf-8"> document.domain = 'wallace-best.com'; if (window.context === undefined) { var context = {}; } context.wallace-bestUrl = 'https://wallace-best.com'; context.wallace-bestDomain = 'wallace-best.com'; context.mediaUrl = '//a.wallace-bestcdn.com/1391808583/'; context.uploadsUrl = '//a.wallace.bestcdn.com/uploads'; context.sslUploadsUrl = '//a.wallace-bestcdn.com/uploads'; context.loginUrl = 'https://wallace-best.com/profile/login/'; context.signupUrl = 'https://wallace-best.com/profile/signup/'; context.apiUrl = '//wallace-best.com/api/3.0/'; context.apiPublicKey = 'Y1S1wGIzdc63qnZ5rhHfjqEABGA4ZTDncauWFFWWTUBqkmLjdxloTb7ilhGnZ7z1'; context.forum = null; context.adminUrl = 'https://wallace-best.com'; context.switches = { "explore_dashboard_2":false, "partitions:api:posts/countPendin":false, "use_rs_paginator_30m":false, "inline_defaults_css":false, "evm_publisher_reports":true, "postsort":false, "enable_entropy_filtering":false, "exp_newnav":true, "organic_discovery_experiments":false, "realtime_for_oldies":false, "firehose_push":true, "website_addons":true, "addons_ab_test":false, "firehose_gnip_http":true, "community_icon":true, "pub_reporting_v2":true, "pd_thumbnail_settings":true, "algorithm_experiments":false, "discovery_log_to_browser":false, "is_last_modified":true, "embed_category_display":false, "partitions:api:forums/listPosts":false, "shardpost":true, "limit_get_posts_days_30d":true, "next_realtime_anim_disabled":false, "juggler_thread_onReady":true, "firehose_realertime":false, "loginas":true, "juggler_enabled":true, "user_onboarding":true, "website_follow_redirect":true, "raven_js":true, "shardpost:index":true, "filter_ads_by_country":true, "new_sort_paginator":true, "threadident_reads":true, "new_media":true, "enable_link_affiliation":true, "show_unapproved":false, "onboarding_profile_editing":true, "partitions":true, "dotcom_marketing":true, "discovery_analytics":true, "exp_newnav_disable":true, "new_community_nav_embed":true, "discussions_tab":true, "embed_less_refactor":false, "use_rs_paginator_60m":true, "embed_labs":false, "auto_flat_sort":false, "disable_moderate_ascending":true, "disable_realtime":true, "partitions:api":true, "digest_thread_votes":true, "shardpost:paginator":false, "debug_js":false, "exp_mn2":false, "limit_get_posts_days_7d":true, "pinnedcomments":false, "use_queue_b":true, "new_embed_profile":true, "next_track_links":true, "postsort:paginator":true, "simple_signup":true, "static_styles":true, "stats":true, "discovery_next":true, "override_skip_syslog":false, "show_captcha_on_links":true, "exp_mn2_force":false, "next_dragdrop_nag":true, "firehose_gnip":true, "firehose_pubsub":true, "rt_go_backend":false, "dark_jester":true, "next_logging":false, "surveyNotice":false, "tipalti_payments":true, "default_trusted_domain":false, "disqus_trends":false, "log_large_querysets":false, "phoenix":false, "exp_autoonboard":true, "lazy_embed":false, "explore_dashboard":true, "partitions:api:posts/list":true, "support_contact_with_frames":true, "use_rs_paginator_5m":true, "limit_textdigger":true, "embed_redirect":false, "logging":false, "exp_mn2_disable":true, "aggressive_embed_cache":true, "dashboard_client":false, "safety_levels_enabled":true, "partitions:api:categories/listPo":false, "next_show_new_media":true, "next_realtime_cap":false, "next_discard_low_rep":true, "next_streaming_realtime":false, "partitions:api:threads/listPosts":false, "textdigger_crawler":true }; context.urlMap = { 'signup': 'https://wallace-best.com/admin/signup/', 'dashboard': 'http://wallace-best.com/dashboard/', 'admin': 'http://wallace-best.com/admin/', 'logout': '//wallace-best.com/logout/', 'home': 'https://wallace-best.com', 'for_websites': 'http://wallace-best.com/websites/', 'login': 'https://wallace-best.com/profile/login/' }; context.navMap = { 'signup': '', 'dashboard': '', 'admin': '', 'addons': '' }; </script> <script src="//a.wallace-bestcdn.com/1391808583/js/src/auth_context.js" type="text/javascript" charset="utf-8"></script> <link rel="stylesheet" href="//a.wallace-bestdn.com/1391808583/build/css/b31fb2fa3905.css" type="text/css" /> <script type="text/javascript" src="//a.wallace-bestcdn.com/1391808583/build/js/5ee01877d131.js"></script> <script> // // shared/foundation.js // // This file contains the absolute minimum code necessary in order // to create a new application in the WALLACE-BEST namespace. // // You should load this file *before* anything that modifies the WALLACE-BEST global. // /*jshint browser:true, undef:true, strict:true, expr:true, white:true */ /*global wallace-best:true */ var WALLACE-BEST = (function (window, undefined) { "use strict"; var wallace-best = window.wallace-best || {}; // Exception thrown from wallace-best.assert method on failure wallace-best.AssertionError = function (message) { this.message = message; }; wallace-best.AssertionError.prototype.toString = function () { return 'Assertion Error: ' + (this.message || '[no message]'); }; // Raises a wallace-best.AssertionError if value is falsy wallace-best.assert = function (value, message, soft) { if (value) return; if (soft) window.console && window.console.log("DISQUS assertion failed: " + message); else throw new wallace-best.AssertionError(message); }; // Functions to clean attached modules (used by define and cleanup) var cleanFuncs = []; // Attaches a new public interface (module) to the wallace-best namespace. // For example, if wallace-best object is { 'a': { 'b': {} } }: // // wallace-best.define('a.b.c', function () { return { 'd': 'hello' }; }); will transform it into // -> { 'a': { 'b': { 'c': { 'd' : hello' }}}} // // and wallace-best.define('a', function () { return { 'x': 'world' }; }); will transform it into // -> { 'a': { 'b': {}}, 'x': 'world' } // // Attach modules to wallace-best using only this function. wallace-best.define = function (name, fn) { /*jshint loopfunc:true */ if (typeof name === 'function') { fn = name; name = ''; } var parts = name.split('.'); var part = parts.shift(); var cur = wallace-best; var exports = (fn || function () { return {}; }).call({ overwrites: function (obj) { obj.__overwrites__ = true; return obj; } }, window); while (part) { cur = (cur[part] ? cur[part] : cur[part] = {}); part = parts.shift(); } for (var key in exports) { if (!exports.hasOwnProperty(key)) continue; /*jshint eqnull:true */ if (!exports.__overwrites__ && cur[key] !== null) { wallace-best.assert(!cur.hasOwnProperty(key), 'Unsafe attempt to redefine existing module: ' + key, true /* soft assertion */); } cur[key] = exports[key]; cleanFuncs.push(function (cur, key) { return function () { delete cur[key]; }; }(cur, key)); } return cur; }; // Alias for wallace-best.define for the sake of semantics. // You should use it when you need to get a reference to another // wallace-best module before that module is defined: // // var collections = wallace-best.use('lounge.collections'); // // wallace-best.use is a single argument function because we don't // want to encourage people to use it instead of wallace-best.define. wallace-best.use = function (name) { return wallace-best.define(name); }; wallace-best.cleanup = function () { for (var i = 0; i < cleanFuncs.length; i++) { cleanFuncs[i](); } }; return wallace-best; })(window); /*jshint expr:true, undef:true, strict:true, white:true, browser:true */ /*global wallace-best:false*/ // // shared/corefuncs.js // wallace-best.define(function (window, undefined) { "use strict"; var wallace-best = window.wallace-best; var document = window.document; var head = document.getElementsByTagName('head')[0] || document.body; var jobs = { running: false, timer: null, queue: [] }; var uid = 0; // Taken from _.uniqueId wallace-best.getUid = function (prefix) { var id = ++uid + ''; return prefix ? prefix + id : id; }; /* Defers func() execution until cond() is true */ wallace-best.defer = function (cond, func) { function beat() { /*jshint boss:true */ var queue = jobs.queue; if (queue.length === 0) { jobs.running = false; clearInterval(jobs.timer); } for (var i = 0, pair; pair = queue[i]; i++) { if (pair[0]()) { queue.splice(i--, 1); pair[1](); } } } jobs.queue.push([cond, func]); beat(); if (!jobs.running) { jobs.running = true; jobs.timer = setInterval(beat, 100); } }; wallace-best.isOwn = function (obj, key) { // The object.hasOwnProperty method fails when the // property under consideration is named 'hasOwnProperty'. return Object.prototype.hasOwnProperty.call(obj, key); }; wallace-best.isString = function (str) { return Object.prototype.toString.call(str) === "[object String]"; }; /* * Iterates over an object or a collection and calls a callback * function with each item as a parameter. */ wallace-best.each = function (collection, callback) { var length = collection.length, forEach = Array.prototype.forEach; if (!isNaN(length)) { // Treat collection as an array if (forEach) { forEach.call(collection, callback); } else { for (var i = 0; i < length; i++) { callback(collection[i], i, collection); } } } else { // Treat collection as an object for (var key in collection) { if (wallace-best.isOwn(collection, key)) { callback(collection[key], key, collection); } } } }; // Borrowed from underscore wallace-best.extend = function (obj) { wallace-best.each(Array.prototype.slice.call(arguments, 1), function (source) { for (var prop in source) { obj[prop] = source[prop]; } }); return obj; }; wallace-best.serializeArgs = function (params) { var pcs = []; wallace-best.each(params, function (val, key) { if (val !== undefined) { pcs.push(key + (val !== null ? '=' + encodeURIComponent(val) : '')); } }); return pcs.join('&'); }; wallace-best.serialize = function (url, params, nocache) { if (params) { url += (~url.indexOf('?') ? (url.charAt(url.length - 1) == '&' ? '': '&') : '?'); url += wallace-best.serializeArgs(params); } if (nocache) { var ncp = {}; ncp[(new Date()).getTime()] = null; return wallace-best.serialize(url, ncp); } var len = url.length; return (url.charAt(len - 1) == "&" ? url.slice(0, len - 1) : url); }; var TIMEOUT_DURATION = 2e4; // 20 seconds var addEvent, removeEvent; // select the correct event listener function. all of our supported // browsers will use one of these if ('addEventListener' in window) { addEvent = function (node, event, handler) { node.addEventListener(event, handler, false); }; removeEvent = function (node, event, handler) { node.removeEventListener(event, handler, false); }; } else { addEvent = function (node, event, handler) { node.attachEvent('on' + event, handler); }; removeEvent = function (node, event, handler) { node.detachEvent('on' + event, handler); }; } wallace-best.require = function (url, params, nocache, success, failure) { var script = document.createElement('script'); var evName = script.addEventListener ? 'load' : 'readystatechange'; var timeout = null; script.src = wallace-best.serialize(url, params, nocache); script.async = true; script.charset = 'UTF-8'; function handler(ev) { ev = ev || window.event; if (!ev.target) { ev.target = ev.srcElement; } if (ev.type != 'load' && !/^(complete|loaded)$/.test(ev.target.readyState)) { return; // Not ready yet } if (success) { success(); } if (timeout) { clearTimeout(timeout); } removeEvent(ev.target, evName, handler); } if (success || failure) { addEvent(script, evName, handler); } if (failure) { timeout = setTimeout(function () { failure(); }, TIMEOUT_DURATION); } head.appendChild(script); return wallace-best; }; wallace-best.requireStylesheet = function (url, params, nocache) { var link = document.createElement('link'); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = wallace-best.serialize(url, params, nocache); head.appendChild(link); return wallace-best; }; wallace-best.requireSet = function (urls, nocache, callback) { var remaining = urls.length; wallace-best.each(urls, function (url) { wallace-best.require(url, {}, nocache, function () { if (--remaining === 0) { callback(); } }); }); }; wallace-best.injectCss = function (css) { var style = document.createElement('style'); style.setAttribute('type', 'text/css'); // Make inline CSS more readable by splitting each rule onto a separate line css = css.replace(/\}/g, "}\n"); if (window.location.href.match(/^https/)) css = css.replace(/http:\/\//g, 'https://'); if (style.styleSheet) { // Internet Explorer only style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style); }; wallace-best.isString = function (val) { return Object.prototype.toString.call(val) === '[object String]'; }; }); /*jshint boss:true*/ /*global wallace-best */ wallace-best.define('Events', function (window, undefined) { "use strict"; // Returns a function that will be executed at most one time, no matter how // often you call it. Useful for lazy initialization. var once = function (func) { var ran = false, memo; return function () { if (ran) return memo; ran = true; memo = func.apply(this, arguments); func = null; return memo; }; }; var has = wallace-best.isOwn; var keys = Object.keys || function (obj) { if (obj !== Object(obj)) throw new TypeError('Invalid object'); var keys = []; for (var key in obj) if (has(obj, key)) keys[keys.length] = key; return keys; }; var slice = [].slice; // Backbone.Events // --------------- // A module that can be mixed in to *any object* in order to provide it with // custom events. You may bind with `on` or remove with `off` callback // functions to an event; `trigger`-ing an event fires all callbacks in // succession. // // var object = {}; // _.extend(object, Backbone.Events); // object.on('expand', function(){ alert('expanded'); }); // object.trigger('expand'); // var Events = { // Bind an event to a `callback` function. Passing `"all"` will bind // the callback to all events fired. on: function (name, callback, context) { if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; this._events = this._events || {}; var events = this._events[name] || (this._events[name] = []); events.push({callback: callback, context: context, ctx: context || this}); return this; }, // Bind an event to only be triggered a single time. After the first time // the callback is invoked, it will be removed. once: function (name, callback, context) { if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; var self = this; var onced = once(function () { self.off(name, onced); callback.apply(this, arguments); }); onced._callback = callback; return this.on(name, onced, context); }, // Remove one or many callbacks. If `context` is null, removes all // callbacks with that function. If `callback` is null, removes all // callbacks for the event. If `name` is null, removes all bound // callbacks for all events. off: function (name, callback, context) { var retain, ev, events, names, i, l, j, k; if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; if (!name && !callback && !context) { this._events = {}; return this; } names = name ? [name] : keys(this._events); for (i = 0, l = names.length; i < l; i++) { name = names[i]; if (events = this._events[name]) { this._events[name] = retain = []; if (callback || context) { for (j = 0, k = events.length; j < k; j++) { ev = events[j]; if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || (context && context !== ev.context)) { retain.push(ev); } } } if (!retain.length) delete this._events[name]; } } return this; }, // Trigger one or many events, firing all bound callbacks. Callbacks are // passed the same arguments as `trigger` is, apart from the event name // (unless you're listening on `"all"`, which will cause your callback to // receive the true name of the event as the first argument). trigger: function (name) { if (!this._events) return this; var args = slice.call(arguments, 1); if (!eventsApi(this, 'trigger', name, args)) return this; var events = this._events[name]; var allEvents = this._events.all; if (events) triggerEvents(events, args); if (allEvents) triggerEvents(allEvents, arguments); return this; }, // Tell this object to stop listening to either specific events ... or // to every object it's currently listening to. stopListening: function (obj, name, callback) { var listeners = this._listeners; if (!listeners) return this; var deleteListener = !name && !callback; if (typeof name === 'object') callback = this; if (obj) (listeners = {})[obj._listenerId] = obj; for (var id in listeners) { listeners[id].off(name, callback, this); if (deleteListener) delete this._listeners[id]; } return this; } }; // Regular expression used to split event strings. var eventSplitter = /\s+/; // Implement fancy features of the Events API such as multiple event // names `"change blur"` and jQuery-style event maps `{change: action}` // in terms of the existing API. var eventsApi = function (obj, action, name, rest) { if (!name) return true; // Handle event maps. if (typeof name === 'object') { for (var key in name) { obj[action].apply(obj, [key, name[key]].concat(rest)); } return false; } // Handle space separated event names. if (eventSplitter.test(name)) { var names = name.split(eventSplitter); for (var i = 0, l = names.length; i < l; i++) { obj[action].apply(obj, [names[i]].concat(rest)); } return false; } return true; }; // A difficult-to-believe, but optimized internal dispatch function for // triggering events. Tries to keep the usual cases speedy (most internal // Backbone events have 3 arguments). var triggerEvents = function (events, args) { var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; switch (args.length) { case 0: while (++i < l) { (ev = events[i]).callback.call(ev.ctx); } return; case 1: while (++i < l) { (ev = events[i]).callback.call(ev.ctx, a1); } return; case 2: while (++i < l) { (ev = events[i]).callback.call(ev.ctx, a1, a2); } return; case 3: while (++i < l) { (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); } return; default: while (++i < l) { (ev = events[i]).callback.apply(ev.ctx, args); } } }; var listenMethods = {listenTo: 'on', listenToOnce: 'once'}; // Inversion-of-control versions of `on` and `once`. Tell *this* object to // listen to an event in another object ... keeping track of what it's // listening to. wallace-best.each(listenMethods, function (implementation, method) { Events[method] = function (obj, name, callback) { var listeners = this._listeners || (this._listeners = {}); var id = obj._listenerId || (obj._listenerId = wallace-best.getUid('l')); listeners[id] = obj; if (typeof name === 'object') callback = this; obj[implementation](name, callback, this); return this; }; }); // Aliases for backwards compatibility. Events.bind = Events.on; Events.unbind = Events.off; return Events; }); // used for /follow/ /login/ /signup/ social oauth dialogs // faking the bus wallace-best.use('Bus'); _.extend(DISQUS.Bus, wallace-best.Events); </script> <script src="//a.disquscdn.com/1391808583/js/src/global.js" charset="utf-8"></script> <script src="//a.disquscdn.com/1391808583/js/src/ga_events.js" charset="utf-8"></script> <script src="//a.disquscdn.com/1391808583/js/src/messagesx.js"></script> <!-- start Mixpanel --><script type="text/javascript">(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!== typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");for(g=0;g<i.length;g++)f(c,i[g]); b._i.push([a,e,d])};b.__SV=1.2}})(document,window.mixpanel||[]); mixpanel.init('17b27902cd9da8972af8a3c43850fa5f', { track_pageview: false, debug: false }); </script><!-- end Mixpanel --> <script src="//a.disquscdn.com/1391808583//js/src/funnelcake.js"></script> <script type="text/javascript"> if (window.AB_TESTS === undefined) { var AB_TESTS = {}; } $(function() { if (context.auth.username !== undefined) { disqus.messagesx.init(context.auth.username); } }); </script> <script type="text/javascript" charset="utf-8"> // Global tests $(document).ready(function() { $('a[rel*=facebox]').facebox(); }); </script> <script type="text/x-underscore-template" data-template-name="global-nav"> <% var has_custom_avatar = data.avatar_url && data.avatar_url.indexOf('noavatar') < 0; %> <% var has_custom_username = data.username && data.username.indexOf('disqus_') < 0; %> <% if (data.username) { %> <li class="<%= data.forWebsitesClasses || '' %>" data-analytics="header for websites"><a href="<%= data.urlMap.for_websites %>">For Websites</a></li> <li data-analytics="header dashboard"><a href="<%= data.urlMap.dashboard %>">Dashboard</a></li> <% if (data.has_forums) { %> <li class="admin<% if (has_custom_avatar || !has_custom_username) { %> avatar-menu-admin<% } %>" data-analytics="header admin"><a href="<%= data.urlMap.admin %>">Admin</a></li> <% } %> <li class="user-dropdown dropdown-toggle<% if (has_custom_avatar || !has_custom_username) { %> avatar-menu<% } else { %> username-menu<% } %>" data-analytics="header username dropdown" data-floater-marker="<% if (has_custom_avatar || !has_custom_username) { %>square<% } %>"> <a href="<%= data.urlMap.home %>/<%= data.username %>/"> <% if (has_custom_avatar) { %> <img src="<%= data.avatar_url %>" class="avatar"> <% } else if (has_custom_username) { %> <%= data.username %> <% } else { %> <img src="<%= data.avatar_url %>" class="avatar"> <% } %> <span class="caret"></span> </a> <ul class="clearfix dropdown"> <li data-analytics="header view profile"><a href="<%= data.urlMap.home %>/<%= data.username %>/">View Profile</a></li> <li class="edit-profile js-edit-profile" data-analytics="header edit profile"><a href="<%= data.urlMap.dashboard %>#account">Edit Profile</a></li> <li class="logout" data-analytics="header logout"><a href="<%= data.urlMap.logout %>">Logout</a></li> </ul> </li> <% } else { %> <li class="<%= data.forWebsitesClasses || '' %>" data-analytics="header for websites"><a href="<%= data.urlMap.for_websites %>">For Websites</a></li> <li class="link-login" data-analytics="header login"><a href="<%= data.urlMap.login %>?next=<%= encodeURIComponent(document.location.href) %>">Log in</a></li> <% } %> </script> <!--[if lte IE 7]> <script src="//a.wallace-bestdn.com/1391808583/js/src/border_box_model.js"></script> <![endif]--> <!--[if lte IE 8]> <script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.5.3/modernizr.min.js"></script> <script src="//a.wallace-bestcdn.com/1391808583/js/src/selectivizr.js"></script> <![endif]--> <meta name="viewport" content="width=device-width, user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <script type="text/javascript" charset="utf-8"> // Network tests $(document).ready(function() { $('a[rel*=facebox]').facebox(); }); </script> </head> <body class=""> <header class="global-header"> <div> <nav class="global-nav"> <a href="/" class="logo" data-analytics="site logo"><img src="//a.wallace-bestcdn.com/1391808583/img/disqus-logo-alt-hidpi.png" width="150" alt="wallace-best" title="wallace-best - Discover your community"/></a> </nav> </div> </header> <section class="login"> <form id="login-form" action="https://disqus.com/profile/login/?next=http://wallace-best.wallace-best.com/admin/moderate/" method="post" accept-charset="utf-8"> <h1>Sign in to continue</h1> <input type="text" name="username" tabindex="20" placeholder="Email or Username" value=""/> <div class="password-container"> <input type="password" name="password" tabindex="21" placeholder="Password" /> <span>(<a href="https://wallace-best.com/forgot/">forgot?</a>)</span> </div> <button type="submit" class="button submit" data-analytics="sign-in">Log in to wallace-best</button> <span class="create-account"> <a href="https://wallace-best.com/profile/signup/?next=http%3A//wallace-best.wallace-best.com/admin/moderate/" data-analytics="create-account"> Create an Account </a> </span> <h1 class="or-login">Alternatively, you can log in using:</h1> <div class="connect-options"> <button title="facebook" type="button" class="facebook-auth"> <span class="auth-container"> <img src="//a.wallace-bestdn.com/1391808583/img/icons/facebook.svg" alt="Facebook"> <!--[if lte IE 7]> <img src="//a.wallace-bestcdn.com/1391808583/img/icons/facebook.png" alt="Facebook"> <![endif]--> </span> </button> <button title="twitter" type="button" class="twitter-auth"> <span class="auth-container"> <img src="//a.wallace-bestdn.com/1391808583/img/icons/twitter.svg" alt="Twitter"> <!--[if lte IE 7]> <img src="//a.wallace-bestcdn.com/1391808583/img/icons/twitter.png" alt="Twitter"> <![endif]--> </span> </button> <button title="google" type="button" class="google-auth"> <span class="auth-container"> <img src="//a.wallace-bestdn.com/1391808583/img/icons/google.svg" alt="Google"> <!--[if lte IE 7]> <img src="//a.wallace-bestcdn.com/1391808583/img/icons/google.png" alt="Google"> <![endif]--> </span> </button> </div> </form> </section> <div class="get-disqus"> <a href="https://wallace-best.com/admin/signup/" data-analytics="get-disqus">Get wallace-best for your site</a> </div> <script> /*jshint undef:true, browser:true, maxlen:100, strict:true, expr:true, white:true */ // These must be global var _comscore, _gaq; (function (doc) { "use strict"; // Convert Django template variables to JS variables var debug = false, gaKey = '', gaPunt = '', gaCustomVars = { component: 'website', forum: '', version: 'v5' }, gaSlots = { component: 1, forum: 3, version: 4 }; /**/ gaKey = gaCustomVars.component == 'website' ? 'UA-1410476-16' : 'UA-1410476-6'; // Now start loading analytics services var s = doc.getElementsByTagName('script')[0], p = s.parentNode; var isSecure = doc.location.protocol == 'https:'; if (!debug) { _comscore = _comscore || []; // comScore // Load comScore _comscore.push({ c1: '7', c2: '10137436', c3: '1' }); var cs = document.createElement('script'); cs.async = true; cs.src = (isSecure ? 'https://sb' : 'http://b') + '.scorecardresearch.com/beacon.js'; p.insertBefore(cs, s); } // Set up Google Analytics _gaq = _gaq || []; if (!debug) { _gaq.push(['_setAccount', gaKey]); _gaq.push(['_setDomainName', '.wallace-best.com']); } if (!gaPunt) { for (var v in gaCustomVars) { if (!(gaCustomVars.hasOwnProperty(v) && gaCustomVars[v])) continue; _gaq.push(['_setCustomVar', gaSlots[v], gaCustomVars[v]]); } _gaq.push(['_trackPageview']); } // Load Google Analytics var ga = doc.createElement('script'); ga.type = 'text/javascript'; ga.async = true; var prefix = isSecure ? 'https://ssl' : 'http://www'; // Dev tip: if you cannot use the Google Analytics Debug Chrome extension, // https://chrome.google.com/webstore/detail/jnkmfdileelhofjcijamephohjechhna // you can replace /ga.js on the following line with /u/ga_debug.js // But if you do that, PLEASE DON'T COMMIT THE CHANGE! Kthxbai. ga.src = prefix + '.google-analytics.com/ga.js'; p.insertBefore(ga, s); }(document)); </script> <script> (function (){ // adds a classname for css to target the current page without passing in special things from the server or wherever // replacing all characters not allowable in classnames var newLocation = encodeURIComponent(window.location.pathname).replace(/[\.!~*'\(\)]/g, '_'); // cleaning up remaining url-encoded symbols for clarity sake newLocation = newLocation.replace(/%2F/g, '-').replace(/^-/, '').replace(/-$/, ''); if (newLocation === '') { newLocation = 'homepage'; } $('body').addClass('' + newLocation); }()); $(function ($) { // adds 'page-active' class to links matching the page url $('a[href="' + window.location.pathname + '"]').addClass('page-active'); }); $(document).delegate('[data-toggle-selector]', 'click', function (e) { var $this = $(this); $($this.attr('data-toggle-selector')).toggle(); e.preventDefault(); }); </script> <script type="text/javascript"> wallace-best.define('web.urls', function () { return { twitter: 'https://wallace-best.com/_ax/twitter/begin/', google: 'https://wallace-best.com/_ax/google/begin/', facebook: 'https://wallace-best.com/_ax/facebook/begin/', dashboard: 'http://wallace-best.com/dashboard/' } }); $(document).ready(function () { var usernameInput = $("input[name=username]"); if (usernameInput[0].value) { $("input[name=password]").focus(); } else { usernameInput.focus(); } }); </script> <script type="text/javascript" src="//a.wallace-bestcdn.com/1391808583/js/src/social_login.js"> <script type="text/javascript"> $(function() { var options = { authenticated: (context.auth.username !== undefined), moderated_forums: context.auth.moderated_forums, user_id: context.auth.user_id, track_clicks: !!context.switches.website_click_analytics, forum: context.forum }; wallace-best.funnelcake.init(options); }); </script> <!-- helper jQuery tmpl partials --> <script type="text/x-jquery-tmpl" id="profile-metadata-tmpl"> data-profile-username="${username}" data-profile-hash="${emailHash}" href="/${username}" </script> <script type="text/x-jquery-tmpl" id="profile-link-tmpl"> <a class="profile-launcher" {{tmpl "#profile-metadata-tmpl"}} href="/${username}">${name}</a> </script> <script src="//a.wallace-bestcdn.com/1391808583/js/src/templates.js"></script> <script src="//a.wallace-bestcdn.com/1391808583/js/src/modals.js"></script> <script> wallace-best.ui.config({ disqusUrl: 'https://disqus.com', mediaUrl: '//a.wallace-bestcdn.com/1391808583/' }); </script> </body> </html>
soosBot-com / PaginationA Python library to easily create embed paginators in discord.py or any fork that uses discord.py 2.0.
knht / Eris Pagination🔀 An extremely easy to use Embed Paginator for the Eris Discord Library
lukazbaum / Discord Bot HandlerA modern Discord Bot Handler, featuring Slash Commands, Prefix Commands, Context Menus, Component Handling, Automatic Intents, Reloadable Modules, Embed Paginators, and more.
DorianAarno / PaginatorA simple embed paginator built for projects made with disnake.
FlamptX / Paginator.pyDiscord paginator for messages and embeds.
sulvii / Miyuki Pagination🌸 A delightfully cute and professional Discord embed paginator for Discord.js v14+ with customizable buttons, themes, and adorable messages
memeismygod / Hackimport asyncio import discord import json import re import random import json import inspect from paginator import Paginator from math import ceil import subprocess import aiohttp import hashlib class PokeBall(discord.Client): def __init__(self, config_path: str, guild_path: str, pokelist_path: str, pokenames_path: str, *args, **kwargs): self.version = "v3.3.2" self.config_path = config_path self.guild_path = guild_path self.pokelist_path = pokelist_path with open(self.guild_path) as f: self.prefix_dict = json.load(f) with open(self.config_path) as f: self.configs = json.load(f) self.prefix = self.configs['command_prefix'] super().__init__() with open(self.pokelist_path, 'r', encoding='utf-8') as f: self.pokelist = f.read().splitlines() self.legendaries = [ 'Arceus', 'Articuno', 'Azelf', 'Celebi', 'Cobalion', 'Cosmoem', 'Cosmog', 'Cresselia', 'Darkrai', 'Deoxys', 'Dialga', 'Diancie', 'Entei', 'Genesect', 'Giratina', 'Groudon', 'Heatran', 'Ho-Oh', 'Hoopa', 'Jirachi', 'Keldeo', 'Kyogre', 'Kyurem', 'Landorus', 'Latias', 'Latios', 'Lugia', 'Lunala', 'Magearna', 'Manaphy', 'Marshadow', 'Meloetta', 'Mesprit', 'Mew', 'Mewtwo', 'Moltres', 'Necrozma', 'Palkia', 'Phione', 'Raikou', 'Rayquaza', 'Regice', 'Regigigas', 'Regirock', 'Registeel', 'Reshiram', 'Shaymin', 'Silvally', 'Solgaleo', 'Suicune', 'Tapu Bulu', 'Tapu Fini', 'Tapu Koko', 'Tapu Lele', 'Terrakion', 'Thundurus', 'Tornadus', 'Type: Null', 'Uxie', 'Victini', 'Virizion', 'Volcanion', 'Xerneas', 'Yveltal', 'Zapdos', 'Zekrom', 'Zeraora', 'Zygarde' ] pokemons = [pokemon.split(' -> ')[0] for pokemon in self.pokelist] self.trash = list({dup for dup in pokemons if pokemons.count(dup) > int(self.configs["max_duplicates"]) - 1}) self.priority_only = self.configs["priority_only"] self.auto_catcher = self.configs["autocatcher"] self.mode = "blacklist" self.guild_mode = "blacklist" self.autolog = self.configs["autolog"] self.ready = False with open(pokenames_path, 'r', encoding='utf-8') as f: self.pokenames = json.load(f) def run(self): super().run(self.configs['token'], bot=False) def refresh_trash(self): pokemons = [pokemon.split(' -> ')[0] for pokemon in self.pokelist] self.trash = list({dup for dup in pokemons if pokemons.count(dup) > int(self.configs["max_duplicates"]) - 1}) def junky_trash(self): def safe_filter(pokemon): names = [pokemon.split(' -> ')[0] for pokemon in self.pokelist] checks = [ pokemon.split(' -> ')[1]!='1', pokemon.split(' -> ')[0] not in ( self.configs['priority'] + self.legendaries ), names.count(pokemon.split(' -> ')[0]) > int(self.configs["max_duplicates"]), len(pokemon.split(' -> ')) <= 3 ] return all(checks) def guard(pokes): limit = int(self.configs['max_duplicates']) pokelist = pokes[:] for poke in pokelist: pokename = poke[0] mons = [mon[0] for mon in pokelist] while mons.count(pokename) > limit: pokelist.pop(mons.index(pokename)) mons = [mon[0] for mon in pokelist] return pokelist results = [pokemon.split(' -> ') for pokemon in self.pokelist if safe_filter(pokemon)] junk = sorted(results, key=(lambda x: (x[0], int(x[2])))) safe = guard(junk) pokes = [poke for poke in junk if poke not in safe] return pokes def is_legend(self, pokemon): return pokemon in self.legendaries def get_id(self, pokename, search=False): def assert_name(pokemon): return pokemon.split(' -> ')[0].lower() == pokename.lower() def search_name(pokemon): return pokename.lower() in pokemon.split(' -> ')[0].lower() results = [] if search: results = [ pokemon.split(' -> ') for pokemon in self.pokelist if search_name(pokemon) ] else: results = [ pokemon.split(' -> ')[1] for pokemon in self.pokelist if assert_name(pokemon) ] return results or "\u200B" def new_guild(self, message, pref): if message.guild.id not in self.prefix_dict.keys(): self.prefix_dict[message.guild.id] = pref.split('catch')[0] with open(self.guild_path, 'w') as f: f.write(json.dumps(self.prefix_dict)) async def match(self, url): async with await self.sess.get(url) as resp: dat = await resp.content.read() m = hashlib.md5(dat).hexdigest() return self.pokenames[m] async def on_message(self, message): def pokecord_reply(msg): return msg.author.id == 365975655608745985 if not self.ready: return if "guild" not in dir(message): #Skip DMs to avoid AttributeError (alt) return if message.guild is None: #Skip DMs to avoid AttributeError return else: blacklist_checks = [ self.mode == "blacklist", message.channel.id in self.configs["blacklists"] ] whitelist_checks = [ self.mode == "whitelist", message.channel.id not in self.configs["whitelists"] ] blackguild_checks = [ self.guild_mode == "blacklist", message.guild.id in self.configs["blacklist_guilds"] ] whiteguild_checks = [ self.guild_mode == "whitelist", message.guild.id not in self.configs["whitelist_guilds"] ] return_checks = [ all(blacklist_checks), all(whitelist_checks), all(blackguild_checks), all(whiteguild_checks) ] if any(return_checks): return #AutoCatcher pokeball_checks = [ message.author.id == 365975655608745985, message.embeds, self.auto_catcher ] if all(pokeball_checks): def log_formatter(pokemon): params = pokemon.split(' | ') name = params[0].replace('**', '') level = params[1].replace('Level: ', '') number = params[2].replace('Number: ', '') return f"{name} -> {number} -> {level}" emb = message.embeds[0] try: embcheck = emb.title.startswith('A wild') except AttributeError: return if embcheck: name = await self.match(emb.image.url.split('?')[0]) name = name.title() if not name: print(f"Unable to find a name for {name1}.") return duplicate_checks = [ name in self.trash, name not in ( self.configs['priority'] + self.legendaries ), self.configs["restrict_duplicates"] ] proc = random.randint(1, 100) sub_checks = [ name in self.configs['priority'], name in self.legendaries ] def catch_checks(name): if self.priority_only: return any(sub_checks) elif not any(sub_checks): catch_subchecks = [ proc <= self.configs['catch_rate'], name not in self.configs['avoid'] ] return all(catch_subchecks) else: return True catcher = catch_checks(name) if catcher: async with message.channel.typing(): pref = emb.description.split()[5] self.new_guild(message, pref) delay_checks = [ self.configs['delay_on_priority'], name in ( self.configs["priority"] + self.legendaries ) ] if all(delay_checks) or not any(sub_checks): await asyncio.sleep(self.configs['delay']) if all(duplicate_checks): print(f"Skipping the duplicate: {name}") return await message.channel.send(f"{pref} {name}") reply = await self.wait_for('message', check=pokecord_reply) if self.user.mentioned_in(reply): print(f'Caught **{name}** in *{message.guild.name}* in #{message.channel.name}') if self.autolog: await message.channel.send(f"{pref.replace('catch','pokemon')} --name {name}") reply = await self.wait_for('message', check=pokecord_reply) if reply.embeds and reply.channel.id == message.channel.id: raw_list = reply.embeds[0].description.splitlines() refined_list = [ log_formatter(pokeline) for pokeline in raw_list if log_formatter(pokeline) not in self.pokelist ] self.pokelist.append(refined_list[0]) with open(self.pokelist_path, 'w', encoding='utf-8') as f: f.write('\n'.join(self.pokelist)) #SelfBot Commands prefix_checks = [ message.content.startswith(self.prefix), message.author.id == self.user.id ] if all(prefix_checks): def arg_check(arg): str_mentions = [str(mention) for mention in raw_mentions] if not raw_mentions: return True checks = [ raw_mentions, arg != '', arg.replace('<@','').replace('>','') not in str_mentions ] return all(checks) raw_mentions = message.raw_mentions or None detokenized = message.content.split(' ') cmd = detokenized[0] args = [] if len(detokenized) > 1: if raw_mentions: args = [ arg for arg in detokenized[1:] if arg_check(arg) ] else: args = [arg for arg in detokenized[1:] if arg != ''] cmd = cmd.replace(self.prefix,'cmd_').lower() try: method = self.__getattribute__(cmd) except AttributeError: # Not a selfbot command, so execute it as a PokeCord command. cmd = cmd.replace('cmd_', '') args.insert(0, cmd) method = self.cmd_poke_exec kwargs = { 'message':message, 'args': args, 'mentions': [] } if message.mentions: kwargs['mentions'] = message.mentions required = inspect.signature(method) required = set(required.parameters.copy()) for key in list(kwargs): if key not in required: kwargs.pop(key, None) if required == set(kwargs): await method(**kwargs) async def cmd_pokelog(self, message, args=[]): def pokecord_reply(msg): if msg.embeds: checks = [ msg.author.id == 365975655608745985, msg.channel.id == message.channel.id, msg.embeds[0].title.startswith('Your pokémon:') ] return all(checks) else: return False def pokecord_edit(before, msg): if msg.embeds: checks = [ msg.author.id == 365975655608745985, msg.channel.id == message.channel.id, msg.embeds[0].title.startswith('Your pokémon:') ] return all(checks) else: return False def log_formatter(pokemon): params = pokemon.split(' | ') name = params[0].replace('**', '') level = params[1].replace('Level: ', '') number = params[2].replace('Number: ', '') if len(params) == 4: nick = params[3].replace('Nickname: ','') return f"{name} -> {number} -> {level} -> {nick}" return f"{name} -> {number} -> {level}" pref = self.prefix_dict.get(str(message.guild.id), None) if pref: page = 1 pokelist = [] if args: page = int(args[0]) if len(args) > 1 and args[1] == 'continue': with open(self.pokelist_path, 'r', encoding='utf-8') as f: pokelist = f.read().splitlines() await message.channel.send(f"{pref}pokemon {args[0]}") else: await message.channel.send(f"{pref}pokemon") reply = await self.wait_for('message', check=pokecord_reply) pokemons = reply.embeds[0].description.split('\n') pokelist += [log_formatter(pokemon) for pokemon in pokemons] await asyncio.sleep(random.randint(2,3)) while True: delme = await message.channel.send(f"{pref}n") try: before, reply = await self.wait_for('message_edit', check=pokecord_edit, timeout=10.0) except: await message.channel.send(f"{pref}pokemon {page + 1}") try: reply = await self.wait_for('message', check=pokecord_reply, timeout=10.0) except: await message.channel.send(f"Logged up to page {page}.") pokemons = reply.embeds[0].description.split('\n') try: await delme.delete() except: pass page += 1 pokelist += [log_formatter(pokemon) for pokemon in pokemons] with open(self.pokelist_path, 'w', encoding='utf-8') as f: f.write('\n'.join(pokelist)) self.pokelist = pokelist if len(pokemons) < 20: break else: await asyncio.sleep(random.randint(5,7)) self.pokelist = pokelist self.refresh_trash() print('Logged all the pokemon successfully.\n') await self.cmd_total(message=message) else: print('No prefix found for this guild.') async def cmd_trade(self, message, mentions, args=[]): def safe_filter(pokemon): checks = [ pokemon.split(' -> ')[1]!='1', pokemon.split(' -> ')[0] not in self.configs['priority'] ] return all(checks) def user_reply(msg): checks = [ msg.author.id == user.id, word in msg.content ] return all(checks) def pokecord_reply(msg): return msg.author.id == 365975655608745985 and msg.channel.id == message.channel.id def pokecord_embed(msg): checks = [ msg.author.id == 365975655608745985, msg.channel.id == message.channel.id, msg.embeds ] return all(checks) def id_extracter(pokemon): params = pokemon.split(' | ') name = params[0].replace('**', '') level = params[1].replace('Level: ', '') number = params[2].replace('Number: ', '') return int(number) user = mentions[0] pref = self.prefix_dict.get(str(message.guild.id), None) if pref: with open(self.pokelist_path,'r', encoding='utf-8') as f: pokelist = f.read().splitlines() if args: if "fav" in args: await message.channel.send(f"{pref}fav") try: reply = await self.wait_for('message', check=pokecord_reply, timeout=2.0) except: await message.channel.send(f"{pref}ping") await message.channel.send(f"{pref}fav") reply = await self.wait_for('message', check=pokecord_reply) if reply.embeds and reply.embeds[0].title == "Your pokémon:": pokemons = reply.embeds[0].description.split('\n') numbers = [id_extracter(pokeline) for pokeline in pokemons] else: numlist = [] for arg in args: if all(char.isalpha() for char in arg): numlist += self.get_id(args[0].title()) else: numlist.append(arg) numbers = numlist else: numbers = [pokemon.split(' -> ')[1] for pokemon in self.pokelist if safe_filter(pokemon)] numbers = sorted(numbers,reverse=True) numbatches = [numbers[i:i+25] for i in range(0, len(numbers), 25)] for numbers in numbatches: await message.channel.send(f"{pref}trade {user.mention}") word = f"{pref}accept" reply = await self.wait_for('message', check=user_reply) confirmation = await self.wait_for('message', check=pokecord_embed) for number in numbers: await message.channel.send(f"{pref}p add {number}") await asyncio.sleep(2.0) await message.channel.send(f"{pref}confirm") confirmation = await self.wait_for('message', check=pokecord_reply) if confirmation.content == "Trade confirmed.": await asyncio.sleep(3.0) else: continue print('Successfully traded away all pokemon.') await self.cmd_pokelog(message) async def cmd_poke_exec(self, message, args=[], mentions=None): pref = self.prefix_dict.get(str(message.guild.id), None) if pref and args: command = args.pop(0) pokeargs = ' '.join(args) pokementions = ' '+' '.join([mention.mention for mention in mentions]) or '' pokecmd = f"{pref}{command}{pokementions}{pokeargs}" await message.channel.send(pokecmd) async def cmd_echo(self, message, args=[], mentions=None): if args: await message.channel.send(f"{' '.join(args)} {' '.join([mention.mention for mention in mentions])}") async def cmd_id(self, message, args=[]): pref = self.prefix_dict.get(str(message.guild.id), None) if pref and args: if len(args) > 1 and args[0] == 'search': pokename = args[1] results = self.get_id(pokename, True) embeds = [] for i in range(0, len(results), 10): embed = discord.Embed(title="Search Results", description="\u200B", color=15728640) if results == "\u200B": continue else: for result in results[i:i+10]: embed.add_field(name=result[0], value=f"**ID**: {result[1]}\n**LEVEL**: {result[2]}", inline=False) embeds.append(embed) try: base = await message.channel.send(content=None, embed=embeds[0]) pager = Paginator(message, base, embeds, self) await pager.run() except: await message.channel.send(":cold_sweat: | No results found.") else: pokename = args[0] results = self.get_id(pokename, True) embed = discord.Embed(title=pokename.title(), description="\u200B", color=15728640) if results == "\u200B": await message.channel.send(":cold_sweat: | No results found.") return else: for result in results: embed.add_field(name="**ID**", value=f"{result[1]}", inline=False) embed.add_field(name="**LEVEL**", value=f"{result[2]}", inline=False) embed.add_field(name="-----", value="\u200B", inline=False) await message.channel.send(content=None, embed=embed) async def cmd_duplicates(self, message, args=[]): pokemons = [pokemon.split(' -> ')[0] for pokemon in self.pokelist] limit = 2 if args: limit = int(args[0]) dups = {dup for dup in pokemons if pokemons.count(dup) >= limit} if len(dups) == 0: await message.channel.send("There is no pokemon with so many duplicates. Try a smaller number.") return dups = list(dups) dups = sorted(dups) embeds = [] for i in range(0, len(dups), 10): embed = discord.Embed(title="Duplicates", description="\u200B", color=15728640) for dup in dups[i:i+10]: results = self.get_id(dup, True) data = [f"**ID**: {result[1]}\t**LEVEL**: {result[2]}" for result in results] data.append('-------------------------------------------------') embed.add_field(name=f"**{dup}**", value='\n'.join(data), inline=False) embed.set_footer(text=f"{(i//10)+1}/{ceil(len(dups)/10)}") embeds.append(embed) base = await message.channel.send(content=None, embed=embeds[0]) pager = Paginator(message, base, embeds, self) await pager.run() async def cmd_legendary(self, message): embeds = [] for i in range(0, len(self.legendaries), 5): embed = discord.Embed(title="Legendaries", description="\u200B", color=15728640) for legend in self.legendaries[i:i+5]: embed.add_field(name=legend, value='\n'.join(self.get_id(legend)), inline=False) embeds.append(embed) base = await message.channel.send(content=None, embed=embeds[0]) pager = Paginator(message, base, embeds, self) await pager.run() async def cmd_total(self, message): await message.channel.send(f"Total number of pokemon:\n{len(self.pokelist)}") async def cmd_mass_release(self, message, args=[]): def pokecord_reply(msg): return msg.author.id == 365975655608745985 and msg.channel.id == message.channel.id def pokecord_embed(msg): checks = [ msg.author.id == 365975655608745985, msg.channel.id == message.channel.id, msg.embeds ] return all(checks) pref = self.prefix_dict.get(str(message.guild.id), None) if pref and args: if "dupes" in (arg.lower() for arg in args): junk = self.junky_trash() numbers = [mon[1] for mon in junk] else: numbers = args numlist = list(set(sorted(numbers, key=lambda x: int(x), reverse=True))) for numbers in numlist: num_str = ' '.join(numbers) await message.channel.send(f"{pref}release {num_str}") desc = await self.wait_for('message', check=pokecord_embed) desc = desc.embeds[0] criticals = ( self.configs["priority"] + self.legendaries ) desc = desc.to_dict()["fields"][0]["value"] for pokemon in criticals: if pokemon in desc: print(f"WOAH! Almost deleted {pokemon}!") return await asyncio.sleep(1.0) await message.channel.send(f"{pref}confirm") await self.wait_for('message', check=pokecord_reply) await self.cmd_pokelog(message) print("Successfully Released all the specified pokemons.") async def cmd_priority_only(self, message, args=[]): if args: if args[0].lower() == 'off': self.priority_only = False print('Catching all pokemons.\n') elif args[0].lower() == 'on': self.priority_only = True print('Catching only priority and legendary pokemon.\n') else: print(args) async def cmd_autocatcher(self, message, args=[]): if args: if args[0].lower() == 'off': self.auto_catcher = False print('Switching to Commands Only mode.\n') elif args[0].lower() == 'on': self.auto_catcher = True print('Activated autocatcher.\n') else: print(args) async def cmd_autolog(self, message, args=[]): if args: if args[0].lower() == 'off': self.autolog = False print('Disabled Autologger.\n') elif args[0].lower() == 'on': self.autolog = True print('Enabled Autologger.\n') else: print(args) async def cmd_toggle_mode(self, message, args=[]): if args and args[0].lower() in ["blacklist", "whitelist"]: self.mode = args[0].lower() print(f"Switched to {args[0].title()} mode.") async def cmd_toggle_guildmode(self, message, args=[]): if args and args[0].lower() in ["blacklist", "whitelist"]: self.guild_mode = args[0].lower() print(f"Switched to {args[0].title()}ed guilds mode.") async def cmd_gift(self, message, mentions, args=[]): def user_reply(msg): checks = [ msg.author.id == user.id, word in msg.content ] return all(checks) def pokecord_reply(msg): return msg.author.id == 365975655608745985 and msg.channel.id == message.channel.id def pokecord_embed(msg): checks = [ msg.author.id == 365975655608745985, msg.channel.id == message.channel.id, msg.embeds ] return all(checks) user = mentions[0] pref = self.prefix_dict.get(str(message.guild.id), None) if pref and args: money = args[0] await message.channel.send(f"{pref}trade {user.mention}") word = f"{pref}accept" reply = await self.wait_for('message', check=user_reply) confirmation = await self.wait_for('message', check=pokecord_embed) await message.channel.send(f"{pref}c add {money}") await asyncio.sleep(2.0) await message.channel.send(f"{pref}confirm") confirmation = await self.wait_for('message', check=pokecord_reply) if confirmation.content == "Trade confirmed.": print(f'Successfully gifted {money}c to {user}.') async def on_ready(self): async def updater(): def bordered(text): # Kudos to xKynn for this. lines = text.splitlines() width = max(len(s) for s in lines) + 2 res = ['┌' + '─' * width + '┐'] for s in lines: res.append('│ ' + (s + ' ' * width)[:width - 1] + '│') res.append('└' + '─' * width + '┘') return '\n'.join(res) async def file_modifier(filename): async with aiohttp.ClientSession(headers=api_headers, loop=self.loop) as sess: async with sess.get(f"{api_base_url}/{filename}") as resp: if ".json" in filename: code = await resp.read() code = code.decode() else: code = await resp.text() with open(filename, 'w', encoding='utf-8') as f: f.write(code) def config_patcher(base_configs): with open('config.json', 'r', encoding='utf-8') as f: configs = json.load(f) if list(configs.keys()) != list(base_configs.keys()): keys = [key for key in list(base_configs.keys()) if key not in list(configs.keys())] for key in keys: configs[key] = base_configs[key] with open('config.json', 'w', encoding='utf-8') as f: f.write(json.dumps(configs, indent=3)) api_base_url = "https://api.github.com/repos/Hyperclaw79/PokeBall-SelfBot/contents" if self.configs["update_checker"]: # For those with error connecting to api.github.com api_headers = { "Accept": "application/vnd.github.v3.raw+json", "User-Agent": f"Pokeball-Selfbot_{self.user}" } async with aiohttp.ClientSession(headers=api_headers, loop=self.loop) as sess: async with sess.get(f"{api_base_url}/_version.json") as resp: ver_data = await resp.read() ver_data = json.loads(ver_data) vnum = int(ver_data["version"].split('v')[1].replace('.', '')) lnum = int(self.version.split('v')[1].replace('.', '')) if vnum > lnum: vtext = 'There is a new version available.\nDownload it for new updates and bug fixes.\n' vtext += f'Your version: {self.version}\nNew Version: {ver_data["version"]}\n' print(bordered(vtext)) if self.configs["auto_update"]: print("Automatic updates are enabled.") await asyncio.sleep(2.0) print(f'Automatically updating to {ver_data["version"]}....') mod_files = [filename for filename in ver_data["modified_files"] if filename not in __file__ and filename != 'config.json'] for _file in mod_files: await file_modifier(_file) await asyncio.sleep(1.0) if "config.json" in ver_data["modified_files"]: async with aiohttp.ClientSession(headers=api_headers, loop=self.loop) as sess: async with sess.get(f"{api_base_url}/config.json") as resp: configs_data = await resp.read() base_configs = json.loads(configs_data) config_patcher(base_configs) await asyncio.sleep(1.0) if "pokeball.py" in ver_data["modified_files"]: await file_modifier("pokeball.py") subprocess.run("run.bat") # Change this to run.sh if you're on a mac/linux self.sess = aiohttp.ClientSession(loop=self.loop) await updater() priorities = self.configs['priority'] prio_list = '\n'.join([ ', '.join(priorities[i:i+5]) for i in range(0, len(priorities), 5) ]) try: blackies = '\n'.join([ ', '.join([str(channel) for channel in self.configs['blacklists'][i:i+5]]) for i in range(0, len(self.configs['blacklists']), 5) ]) except: blackies = "None" try: whities = '\n'.join([ ', '.join([str(channel) for channel in self.configs['whitelists'][i:i+5]]) for i in range(0, len(self.configs['whitelists']), 5) ]) except: whities = "None" try: blackgs = '\n\t'.join([ ', '.join([str(channel) for channel in self.configs['blacklist_guilds'][i:i+5]]) for i in range(0, len(self.configs['blacklist_guilds']), 5) ]) except: blackgs = "None" try: whitigs = '\n\t'.join([ ', '.join([str(channel) for channel in self.configs['whitelist_guilds'][i:i+5]]) for i in range(0, len(self.configs['whitelist_guilds']), 5) ]) except: whitigs = "None" print( f"\n---PokeBall SelfBot {self.version}----\n\n" f"Bot name: {self.user}\n\n" f"Command Prefix: {self.configs['command_prefix']}\n\n" f"Priority:\n~~~~~~~~~\n{prio_list}\n\n" f"Catch Rate: {self.configs['catch_rate']}%\n\n" f"Catch Delay: {self.configs['delay']} seconds\n\n" f"Delay On Priority: {'On' if self.configs['delay_on_priority'] == True else 'Off'}\n\n" f"Restrict Catching of Duplicates: {'On' if self.configs['delay_on_priority'] == True else 'Off'}\n\n" f"Maximum Number of Duplicates: {self.configs['max_duplicates']}\n\n" f"Blacklisted Channels:\n~~~~~~~~~~~~~~~~~~~~\n{blackies}\n\n" f"Whitelisted Channels:\n~~~~~~~~~~~~~~~~~~~~\n{whities}\n\n" f"Blacklisted Guilds:\n~~~~~~~~~~~~~~~~~~~~\n{blackgs}\n\n" f"Whitelisted Guilds:\n~~~~~~~~~~~~~~~~~~~~\n{whitigs}\n\n" f"Autocatcher: {'On' if self.configs['autocatcher'] == True else 'Off'}\n\n" f"Priority Only: {'On' if self.configs['priority_only'] == True else 'Off'}\n\n" ) self.ready = True