def __init__(self, config): self.config = config self.client = APIClient(config.token) self.shards = {} self.config.shard_count = self.client.gateway_bot_get()['shards'] if self.config.shard_count > 1: self.config.shard_count = 10
def main(): # Initialize the client print("Starting up...") # client = discord.Client() client = APIClient(settings.BOT_TOKEN) # Define event handlers for the client # on_ready may be called multiple times in the event of a reconnect, # hence the running flag @client.event async def on_ready(): if this.running: return this.running = True # Set the playing status if settings.NOW_PLAYING: print("Setting NP game", flush=True) await client.change_presence(game=discord.Game( name=settings.NOW_PLAYING)) print("Logged in!", flush=True) # Load all events print("Loading events...", flush=True) n_ev = 0 for ev in BaseEvent.__subclasses__(): event = ev() sched.add_job(event.run, 'interval', (client, ), minutes=event.interval_minutes) n_ev += 1 sched.start() print(f"{n_ev} events loaded", flush=True) # The message handler for both new message and edits async def common_handle_message(message): text = message.content if text.startswith( settings.COMMAND_PREFIX) and text != settings.COMMAND_PREFIX: cmd_split = text[len(settings.COMMAND_PREFIX):].split() try: await message_handler.handle_command(cmd_split[0].lower(), cmd_split[1:], message, client) except: print("Error while handling message", flush=True) raise @client.event async def on_message(message): await common_handle_message(message) @client.event async def on_message_edit(before, after): await common_handle_message(after) # Finally, set the bot running client.run(settings.BOT_TOKEN)
def __init__(self): self.client = None self.avatars = {} if self.TOKEN and not settings.IS_TEST: self.client = APIClient(self.TOKEN) members = self.client.guilds_members_list(self.GUILD).values() for member in members: self.avatars[member.user.username] = member.user.avatar_url for member in members: self.avatars[member.name] = member.user.avatar_url
def guild_delete(guild): if not g.user.admin: return '', 401 from disco.api.client import APIClient client = APIClient(current_app.config['token']) client.users_me_guilds_delete(guild.guild_id) guild.enabled = False guild.save() return '', 204
def __init__(self, config): super(Client, self).__init__() self.config = config self.events = Emitter() self.packets = Emitter() self.api = APIClient(self.config.token, self) self.gw = GatewayClient(self, self.config.max_reconnects, self.config.encoder) self.state = State(self, StateConfig(self.config.get('state', {}))) if self.config.manhole_enable: self.manhole_locals = { 'client': self, 'state': self.state, 'api': self.api, 'gw': self.gw, } self.manhole = DiscoBackdoorServer( self.config.manhole_bind, banner='Disco Manhole', localf=lambda: self.manhole_locals) self.manhole.start()
class AutoSharder(object): def __init__(self, config): self.config = config self.client = APIClient(config.token) self.shards = {} self.config.shard_count = self.client.gateway_bot_get()['shards'] if self.config.shard_count > 1: self.config.shard_count = 10 def run_on(self, sid, raw): func = load_function(raw) return self.shards[sid].execute(func).wait(timeout=15) def run(self): for shard in range(self.config.shard_count): if self.config.manhole_enable and shard != 0: self.config.manhole_enable = False self.start_shard(shard) gevent.sleep(6) logging.basicConfig( level=logging.INFO, format= '{} [%(levelname)s] %(asctime)s - %(name)s:%(lineno)d - %(message)s' .format(id)) def start_shard(self, sid): cpipe, ppipe = gipc.pipe(duplex=True, encoder=marshal.dumps, decoder=marshal.loads) gipc.start_process(run_shard, (self.config, sid, cpipe)) self.shards[sid] = GIPCProxy(self, ppipe)
def __init__(self, settings, client=None, max_channels_per_category=50): """Accepts Django settings object and optional Discord APIClient (for testing).""" self._client = client or APIClient(settings.DISCORD_API_TOKEN) self._guild_id = settings.DISCORD_GUILD_ID self._puzzle_category_name = settings.DISCORD_PUZZLE_CATEGORY self._archived_category_name = settings.DISCORD_ARCHIVE_CATEGORY self._puzzle_announcements_id = settings.DISCORD_PUZZLE_ANNOUNCEMENTS_CHANNEL self._max_channels_per_category = max_channels_per_category
def execute_url(cls, url, **kwargs): from disco.api.client import APIClient results = WEBHOOK_URL_RE.findall(url) if len(results) != 1: return Exception('Invalid Webhook URL') return cls(id=results[0][0], token=results[0][1]).execute(client=APIClient(None), **kwargs)
class AutoSharder(object): def __init__(self, config): self.config = config self.client = APIClient(config.token) self.shards = {} self.config.shard_count = self.client.gateway_bot_get()['shards'] if self.config.shard_count > 1: self.config.shard_count = 10 def run_on(self, sid, raw): func = load_function(raw) return self.shards[sid].execute(func).wait(timeout=15) def run(self): for shard in range(self.config.shard_count): if self.config.manhole_enable and shard != 0: self.config.manhole_enable = False self.start_shard(shard) gevent.sleep(6) logging.basicConfig( level=logging.INFO, format= '{} [%(levelname)s] %(asctime)s - %(name)s:%(lineno)d - %(message)s' .format(id)) @staticmethod def dumps(data): if isinstance(data, (basestring, int, long, bool, list, set, dict)): return '\x01' + marshal.dumps(data) elif isinstance(data, object) and data.__class__.__name__ == 'code': return '\x01' + marshal.dumps(data) else: return '\x02' + pickle.dumps(data) @staticmethod def loads(data): enc_type = data[0] if enc_type == '\x01': return marshal.loads(data[1:]) elif enc_type == '\x02': return pickle.loads(data[1:]) def start_shard(self, sid): cpipe, ppipe = gipc.pipe(duplex=True, encoder=self.dumps, decoder=self.loads) gipc.start_process(run_shard, (self.config, sid, cpipe)) self.shards[sid] = GIPCProxy(self, ppipe)
def get_root_rwr_servers_status(): """Check the status of the RWR root servers.""" from models import RwrRootServer, RwrRootServerStatus, Variable from disco.api.client import APIClient as DiscordAPIClient from flask import url_for from rwrs import db import rwr.constants import helpers import arrow click.echo('Pinging servers') hosts_to_ping = [server['host'] for group in rwr.constants.ROOT_RWR_SERVERS for server in group['servers']] rwr_root_servers = RwrRootServer.query.filter(RwrRootServer.host.in_(hosts_to_ping)).all() rwr_root_servers_by_host = {rwr_root_server.host: rwr_root_server for rwr_root_server in rwr_root_servers} servers_down_count_then = sum([1 for rwr_root_server in rwr_root_servers if rwr_root_server.status == RwrRootServerStatus.DOWN]) servers_down_count_now = 0 for host in hosts_to_ping: click.echo(host, nl=False) is_server_up = helpers.ping(host) if is_server_up: click.secho(' Up', fg='green') else: click.secho(' Down', fg='red') servers_down_count_now += 1 if host not in rwr_root_servers_by_host: rwr_root_server = RwrRootServer() rwr_root_server.host = host else: rwr_root_server = rwr_root_servers_by_host[host] rwr_root_server.status = RwrRootServerStatus.UP if is_server_up else RwrRootServerStatus.DOWN db.session.add(rwr_root_server) Variable.set_value('last_root_rwr_servers_check', arrow.utcnow().floor('minute')) click.echo('Persisting to database') db.session.commit() message = None if servers_down_count_then == 0 and servers_down_count_now > 0: with app.app_context(): message = ':warning: Online multiplayer is having issues right now. Are the devs aware? If not, poke **pasik** or **JackMayol**. Some details here: {}'.format(url_for('online_multiplayer_status', _external=True)) elif servers_down_count_then > 0 and servers_down_count_now == 0: message = ':white_check_mark: Outage update: online multiplayer is back up and running!' if message: click.echo('Sending Discord bot message') discord_api_client = DiscordAPIClient(app.config['DISCORD_BOT_TOKEN']) discord_api_client.channels_messages_create(app.config['DISCORD_BOT_CHANNEL_ID'], message) click.secho('Done', fg='green')
def __init__(self, settings, client=None, max_channels_per_category=50): """Accepts Django settings object and optional Discord APIClient (for testing).""" self._client = client or APIClient(settings.DISCORD_API_TOKEN) self._max_channels_per_category = max_channels_per_category
def __init__(self): self.client = None self.avatars = None if self.TOKEN and not settings.IS_TEST: self.client = APIClient(self.TOKEN)
class DiscordInterface: TOKEN = None # FIXME a long token from Discord # the next two should be big decimal numbers; in Discord, you can right # click and Copy ID to get them GUILD = 'FIXME' HINT_CHANNEL = 'FIXME' # You also need to enable the "Server Members Intent" under the "Privileged # Gateway Intents" section of the "Bot" page of your application from the # Discord Developer Portal. Or you can comment out the code that # initializes `self.avatars` below. def __init__(self): self.client = None self.avatars = None if self.TOKEN and not settings.IS_TEST: self.client = APIClient(self.TOKEN) def get_avatars(self): if self.avatars is None: self.avatars = {} if self.client is not None: members = self.client.guilds_members_list(self.GUILD).values() for member in members: self.avatars[member.user.username] = member.user.avatar_url for member in members: self.avatars[member.name] = member.user.avatar_url return self.avatars # If you get an error code 50001 when trying to create a message, even # though you're sure your bot has all the permissions, it might be because # you need to "connect to and identify with a gateway at least once"?? # https://discord.com/developers/docs/resources/channel#create-message # I spent like four hours trying to find weird asynchronous ways to do this # right before each time I send a message, but it seems maybe you actually # just need to do this once and your bot can create messages forever? # disco.py's Client (not APIClient) wraps an APIClient and a GatewayClient, # the latter of which does this. So I believe you can fix this by running a # script like the following *once* on your local machine (it will, as # advertised, run forever; just kill it after a few seconds)? # from gevent import monkey # monkey.patch_all() # from disco.client import Client, ClientConfig # Client(ClientConfig({'token': TOKEN})).run_forever() def update_hint(self, hint): HintsConsumer.send_to_all( json.dumps({ 'id': hint.id, 'content': render_to_string('hint_list_entry.html', { 'hint': hint, 'now': timezone.localtime() }) })) embed = MessageEmbed() embed.author.url = hint.full_url() if hint.claimed_datetime: embed.color = 0xdddddd embed.timestamp = hint.claimed_datetime.isoformat() embed.author.name = 'Claimed by {}'.format(hint.claimer) if hint.claimer in self.get_avatars(): embed.author.icon_url = self.get_avatars()[hint.claimer] debug = 'claimed by {}'.format(hint.claimer) else: embed.color = 0xff00ff embed.author.name = 'U N C L A I M E D' claim_url = hint.full_url(claim=True) embed.title = 'Claim: ' + claim_url embed.url = claim_url debug = 'unclaimed' if self.client is None: message = hint.long_discord_message() logger.info('Hint, {}: {}\n{}'.format(debug, hint, message)) logger.info('Embed: {}'.format(embed.to_dict())) elif hint.discord_id: try: self.client.channels_messages_modify(self.HINT_CHANNEL, hint.discord_id, embed=embed) except Exception: dispatch_general_alert( 'Discord API failure: modify\n{}'.format( traceback.format_exc())) else: message = hint.long_discord_message() try: discord_id = self.client.channels_messages_create( self.HINT_CHANNEL, message, embed=embed).id except Exception: dispatch_general_alert( 'Discord API failure: create\n{}'.format( traceback.format_exc())) return hint.discord_id = discord_id hint.save(update_fields=('discord_id', )) def clear_hint(self, hint): HintsConsumer.send_to_all(json.dumps({'id': hint.id})) if self.client is None: logger.info('Hint done: {}'.format(hint)) elif hint.discord_id: # try: # self.client.channels_messages_delete( # self.HINT_CHANNEL, hint.discord_id) # except Exception: # dispatch_general_alert('Discord API failure: delete\n{}'.format( # traceback.format_exc())) # hint.discord_id = '' # hint.save(update_fields=('discord_id',)) # what DPPH did instead of deleting messages: # (nb. I tried to make these colors color-blind friendly) embed = MessageEmbed() if hint.status == 'ANS': embed.color = 0xaaffaa elif hint.status == 'REF': embed.color = 0xcc6600 # nothing for obsolete embed.author.name = '{} by {}'.format(hint.status, hint.claimer) embed.author.url = hint.full_url() embed.description = hint.response[:250] if hint.claimer in self.get_avatars(): embed.author.icon_url = self.get_avatars()[hint.claimer] debug = 'claimed by {}'.format(hint.claimer) try: self.client.channels_messages_modify( self.HINT_CHANNEL, hint.discord_id, content=hint.short_discord_message(), embed=embed) except Exception: dispatch_general_alert( 'Discord API failure: modify\n{}'.format( traceback.format_exc()))
def __init__(self): self.api = APIClient(settings.DISCORD_BOT_TOKEN) self.guild = self.api.http(Routes.USERS_ME_GUILDS_LIST).json()[0]
class DiscordAPI: def __init__(self): self.api = APIClient(settings.DISCORD_BOT_TOKEN) self.guild = self.api.http(Routes.USERS_ME_GUILDS_LIST).json()[0] def is_user_in_guild(self, user_id): members = self.api.guilds_members_list(self.guild['id']).keys() return int(user_id) in members def kick_member(self, user_id): try: reason = "User no longer had the correct access level for discord" self.api.guilds_members_kick(self.guild['id'], user_id, reason) return True except: return False def set_name(self, user_id, name): try: self.api.guilds_members_modify(self.guild['id'], user_id, nick=name) return True except: return False # Roles is a list of role name strings def update_roles(self, user_id, roles): # Find roles we need to create guild_roles = self.api.guilds_roles_list(self.guild['id']) guild_roles_map = map(lambda x: x.name, guild_roles) for role_name in Set(roles).difference(guild_roles_map): role = self.api.guilds_roles_create(self.guild['id']) self.api.guilds_roles_modify(self.guild['id'], role.id, name=role_name) guild_roles.append(role) # Build snowflake list snowflakes = [] for role in roles: snowflakes.append(filter(lambda x: x.name == role, guild_roles)[0].id) self.api.guilds_members_modify(self.guild['id'], user_id, roles=snowflakes)
def create_client(): return APIClient(env("DISCORD_TOKEN", default=""))