def _online_tibia(self):
"""Get total players playing"""
url = "http://www.tibia.com/community/?subtopic=worlds"
try:
async with aiohttp.get(url) as response:
soup = BeautifulSoup(await response.text(), "html.parser")
div1 = soup.find('div', attrs={'id': 'RightArtwork'})
div2 = div1.find('div', attrs={'id': 'PlayersOnline'})
test = div2.get_text()
test1 = test.replace("Players Online", "")
new = "Players currently playing Tibia: " + test1
# div2 = div1.find('div', attrs={'class': 'Border_2'})
# div3 = div2.find('div', attrs={'class': 'Border_3'})
# table = div3.find_all('table', attrs={'class': 'Table1'})
# tr = table.find_all('tr')
# tbody = div4.find('div', attrs={'class': 'CaptionInnerContainer'})
await self.bot.say(str(new))
except:
await self.bot.say("Could not retrive data. The webserver may be offline.")
python类get()的实例源码
def _server_tibia(self, servername):
"""Get Server Info"""
servername = servername.title()
url = "https://secure.tibia.com/community/?subtopic=worlds&world=" + str(servername)
try:
async with aiohttp.get(url) as response:
soup = BeautifulSoup(await response.text(), "html5lib")
b = soup.find_all("table", attrs={'class': 'Table1'})
new = []
rows = b[1].tbody.div.find_all('td')
for row in rows:
new.append(row.get_text())
k = new[::2]
l = new[1::2]
zipped = list(zip(k, l))
t = tabulate(zipped, headers=["Category", "Info"])
await self.bot.say("```Python" + "\n" + str(t) + "```")
except:
await self.bot.say("Unable to retrive server data. The webserver may be offline.")
def add_smug(self, ctx, path):
allowed_content = {'image/jpeg': 'jpg', 'image/png': 'png', 'image/gif': 'gif'}
if not global_methods.is_admin(ctx.message.author):
await self.bot.say("You're not a big boy")
async with aiohttp.get(path) as r:
if r.status == 200:
file = await r.content.read()
type = r.headers['Content-Type']
if type not in allowed_content:
await self.bot.say("That kind of file is not allowed")
return
else:
hash = hashlib.md5(file).hexdigest()
filename = "smug-anime-faces/{}.{}".format(hash, allowed_content[type])
with open(filename, 'wb') as f:
f.write(file)
await self.bot.say("Smugness levels increased")
def suggest(self, ctx, *, suggestion : str):
"""Sends a suggestion to the owner."""
if settings.owner == "id_here":
await self.bot.say("I have no owner set, cannot suggest.")
return
owner = discord.utils.get(self.bot.get_all_members(), id=settings.owner)
author = ctx.message.author
if ctx.message.channel.is_private is False:
server = ctx.message.server
source = "server **{}** ({})".format(server.name, server.id)
else:
source = "direct message"
sender = "**{}** ({}) sent you a suggestion from {}:\n\n".format(author, author.id, source)
message = sender + suggestion
try:
await self.bot.send_message(owner, message)
except discord.errors.InvalidArgument:
await self.bot.say("I cannot send your message, I'm unable to find"
" my owner... *sigh*")
except discord.errors.HTTPException:
await self.bot.say("Your message is too long.")
except:
await self.bot.say("I'm unable to deliver your message. Sorry.")
else:
await self.bot.say("Your message has been sent.")
def bugreport(self, ctx, *, bug:str):
"""Report a bug in the bot."""
if settings.owner == "id_here":
await self.bot.say("I have no owner set, cannot report the bug.")
return
owner = discord.utils.get(self.bot.get_all_members(), id=settings.owner)
author = ctx.message.author
if ctx.message.channel.is_private is False:
server = ctx.message.server
source = "server **{}** ({})".format(server.name, server.id)
else:
source = "direct message"
sender = "**{0}** ({0.id}) sent you a bug report from {1}:\n\n".format(author, source)
message = sender + bug
try:
await self.bot.send_message(owner, message)
except discord.errors.InvalidArgument:
await self.bot.say("I cannot send your bug report, I'm unable to find my owner... *sigh*")
except discord.errors.HTTPException:
await self.bot.say("Your bug report is too long.")
except:
await self.bot.say("I'm unable to deliver your bug report. Sorry.")
else:
await self.bot.say("Your bug report has been sent.")
def list(self):
"""List all available currency codes."""
request = requests.get("http://free.currencyconverterapi.com/api/v3/currencies")
msg = "```Name\t\t\t\t\t\t\tCode\tSymbol\n\n"
request = json.loads(request.content.decode("utf-8"))
for currencycode in request['results']:
if 'currencySymbol' in request['results'][currencycode]:
if len(request['results'][currencycode]['currencyName']) > 26:
request['results'][currencycode]['currencyName'] = request['results'][currencycode]['currencyName'][:26] + "..."
msg += "{}{}".format(request['results'][currencycode]['currencyName'], " " * (32 - len(request['results'][currencycode]['currencyName'])))
msg += "{}{}".format(request['results'][currencycode]['id'], " " * 5)
msg += "{}\n".format(request['results'][currencycode]['currencySymbol'])
else:
msg += "{}{}".format(request['results'][currencycode]['currencyName'], " " * (32 - len(request['results'][currencycode]['currencyName'])))
msg += "{}\n".format(request['results'][currencycode]['id'])
if len(msg) > 1750:
await self.bot.say(msg + "```")
msg = "```"
def _join(self, ctx, *, call_line: str):
"""Joins/creates a call-line between channels"""
call_line = call_line.lower()
if call_line == 'random':
if len(self.call_lines) != 0:
findcall = random.choice(list(self.call_lines))
await self.call_lines[findcall].addChannel(ctx.message.channel)
else:
await self.bot.say("There are no call-lines open! You can make your own call-line with `&call join <name>`")
else:
findcall = self.call_lines.get(call_line)
if findcall is None:
self.call_lines[call_line] = CallLine(
self.bot, ctx.message, call_line)
await self.bot.say("Connected to call-line `{}`".format(call_line))
else:
await findcall.addChannel(ctx.message.channel)
def minecraft(message, client):
r = lambda: random.randint(0,255)
rr = ('0x%02X%02X%02X' % (r(),r(),r()))
loop = asyncio.get_event_loop()
mc_server = message.content.replace(message.content.split()[0] + ' ', '')
async with aiohttp.get('https://mcapi.us/server/status?ip=' + mc_server) as mcr:
if mcr.status == 200:
js = await mcr.json()
mc_details = discord.Embed(title='', description='', colour=int(rr, 16))
if js['server']['name'] != '':
mc_details.add_field(name='Server Version: ', value=js['server']['name'])
if js['online'] == 'True':
mc_details.add_field(name='Server Online:', value=':thumbsup:')
elif js['online'] == 'False':
mc_details.add_field(name='Server Online:', value=':thumbsdown:')
mc_details.add_field(name='Players:', value=str(js['players']['now']) + '/' + str(js['players']['max']))
if js['motd'] != '':
mc_details.add_field(name='Description:', value=js['motd'].replace('§', ''))
await client.send_message(message.channel, embed=mc_details)
else:
await client.send_message(message.channel, 'Something went wrong with the API! :scream:')
def __init__(self, bot):
self.bot = bot
#self.loop = AbstractEventLoop.run_in_executor()
"""def get_cards(self):
#You can change for fitting your language deDE, enUS, esES, esMX,
#frFR, itIT, jaJP, koKR, plPL, ptBR, ruRU, thTH, zhCN, zhTW
response = requests.get('https://api.hearthstonejson.com/v1/12574/enUS/cards.collectible.json')#, 'https://api.hearthstonejson.com/v1/13619/enUS/cards.collectible.json', 'https://api.hearthstonejson.com/v1/15181/enUS/cards.collectible.json', 'https://api.hearthstonejson.com/v1/15300/enUS/cards.collectible.json')#
data = response.json()
return data
@commands.command()
async def hearthcard(self, args):
data = get_cards()
cardname = data['"name": 'args]
attack = data['"attack": ']
if data["type": "MINION"] == True:
await self.bot.say('**{0}** \n' +
"""
def hearthwiki(self, title, ctx):
"""Returns a hearthstone wiki page: ,hearthwiki 'card name'"""
url = 'http://hearthstone.wikia.com/wiki/' + urlquote(title)
typetochan = ctx.message.channel
async with aiohttp.get(url) as resp:
if resp.status == 404:
await self.bot.send_typing(typetochan)
await asyncio.sleep(1)
await self.bot.say('Could not find your page. Try a search:\n{0.url}'.format(resp))
elif resp.status == 200:
await self.bot.send_typing(typetochan)
await asyncio.sleep(1)
await self.bot.say(resp.url)
elif resp.status == 502:
await self.bot.send_typing(typetochan)
await asyncio.sleep(1)
await self.bot.say('Seems like the Hearthstone Wiki is taking too long to respond. Try again later.')
else:
await self.bot.send_typing(typetochan)
await self.bot.say('An error has occurred of status code {0.status} happened. Tell Inkx.'.format(resp))
def youtube_info(message):
if not hasattr(config, "youtube_api_key"):
return
link_re = re.compile(r"""(?:https?://)(?:www\.)?(?:(?:youtube\.com(?:/embed/|/watch/?\?(?:.*)v=))|youtu\.be/)(?P<id>[A-Za-z0-9-_]+)""")
match = link_re.search(message.text)
if not match:
return
params = {
"id": match.group("id"),
"part": "contentDetails,statistics,snippet",
"key": config.youtube_api_key
}
async with aiohttp.get("https://www.googleapis.com/youtube/v3/videos", params=params) as resp:
if resp.status != 200:
return
info = await resp.json()
things = dict()
things.update(info["items"][0]["snippet"])
things.update(info["items"][0]["statistics"])
reply = "YouTube: {title} by {channelTitle} ({viewCount} views)".format(**things)
await message.reply(reply)
def emote(self, ctx, emote_name: str):
"""Enabled emote and all emotes from same twitch channel"""
server = ctx.message.server
if not self._is_enabled(server):
await self.bot.say("Emotes are not enabled on this server.")
return
server_emotes = self.available_emotes[server.id]
if emote_name in server_emotes:
await self.bot.say(
"This server already has '{}'".format(emote_name))
return
await self.bot.say("Retrieving emotes from '{}'.".format(emote_name) +
" Please wait a moment.")
for emote in self.emote_list:
if emote_name == emote.get("regex", ""):
chan_id = emote["images"][0].get("emoticon_set", -1)
if chan_id == -1:
await self.bot.say("Yeah, something failed, try again "
"later?")
return
await self._add_emote(server, chan_id)
await self.bot.say("'{}' and other ".format(emote_name) +
"channel emotes added.")
return
await self.bot.say("No such emote '{}' found.".format(emote_name))
def twitch_online(self, stream):
session = aiohttp.ClientSession()
url = "https://api.twitch.tv/kraken/streams/" + stream
header = {'Client-ID': self.settings.get("TWITCH_TOKEN", "")}
try:
async with session.get(url, headers=header) as r:
data = await r.json()
await session.close()
if r.status == 400:
return 400
elif r.status == 404:
return 404
elif data["stream"] is None:
return False
elif data["stream"]:
return True
except:
return "error"
return "error"
def gif(self, *text):
"""Retrieves first search result from giphy
gif [keyword]"""
if len(text) > 0:
if len(text[0]) > 1 and len(text[0]) < 20:
try:
msg = "+".join(text)
search = "http://api.giphy.com/v1/gifs/search?q=" + msg + "&api_key=dc6zaTOxFJmzC"
async with aiohttp.get(search) as r:
result = await r.json()
if result["data"] != []:
url = result["data"][0]["url"]
await self.bot.say(url)
else:
await self.bot.say("Your search terms gave no results.")
except:
await self.bot.say("Error.")
else:
await self.bot.say("Invalid search.")
else:
await self.bot.say("gif [text]")
def temp(self, location, country: str=None):
"""Make sure to get your own API key and put it into data/weather/settings.json
\nYou can get an API key from: www.wunderground.com/weather/api/"""
if country is None:
country = self.settings["defCountry"]
url = "http://api.wunderground.com/api/" + self.settings['api_key'] + "/conditions/q/" + country + "/" + location +".json"
async with aiohttp.get(url) as r:
data = await r.json()
if "current_observation" in data:
tempCO = data["current_observation"].get("temperature_string", False)
tempW = data["current_observation"].get("weather", " ")
tempC = data["current_observation"].get("temp_c", " ")
tempF = data["current_observation"].get("temp_f", " ")
tempH = data["current_observation"].get("relative_humidity", " ")
if tempCO != False:
if self.settings["unit"] == "C":
await self.bot.say("**Weather **{} **Temp.** {}{} **Hum. **{} ".format(tempW, str(tempC), u"\u2103", tempH))
elif self.settings["unit"] == "F":
await self.bot.say("**Weather **{} **Temp.** {}F **Hum. **{} ".format(tempW, str(tempF), tempH))
else:
await self.bot.say("No temperature found")
else:
await self.bot.say("`Please use a US zip code or format like: paris fr\nIf the default country is set to your requesting location just '!temp city' will do.\nThe the default country is set to: {} `".format(self.settings["defCountry"]))
def default(self, *, channel: "channel"):
"""Default response."""
response = await (await aiohttp.get(
"https://beam.pro/api/v1/channels/{}".format(channel)
)).json()
if "id" in response:
data = await (await aiohttp.get(
self.BEAM_MANIFEST_URL.format(channel=response["id"])
)).json()
if "startedAt" in data:
time = datetime.datetime.utcnow() - datetime.datetime.strptime(
data["startedAt"], "%Y-%m-%dT%H:%M:%S.%fZ")
time -= datetime.timedelta(microseconds=time.microseconds)
return "Channel has been live for {}.".format(time)
return "Channel is offline."
def inspirational(self):
"""Retrieve an inspirational quote."""
try:
data = await (await get(
"http://api.forismatic.com/api/1.0/",
params=dict(method="getQuote", lang="en", format="json")
)).json()
except Exception:
return MessagePacket(
"Unable to get an inspirational quote. Have a ",
("emoji", "??"),
" instead."
)
else:
return "\"{quote}\" -{author}".format(
quote=data["quoteText"].strip(),
author=data["quoteAuthor"].strip() or "Unknown"
)
def subreddit_hot(self, ctx, subreddit: str, post_count: int=3):
"""Command for getting subreddit's hot posts"""
if post_count <= 0 or post_count > 100:
await self.bot.say("Sorry, I can't do that")
else:
url = "https://oauth.reddit.com/r/{}/hot".format(subreddit)
url += "?limit=" + str(post_count)
headers = {
"Authorization": "bearer " + self.access_token,
"User-Agent": "Red-DiscordBotRedditCog/0.1 by /u/palmtree5"
}
async with aiohttp.get(url, headers=headers) as req:
resp_json = await req.json()
if "data" not in resp_json and resp_json["error"] == 403:
await self.bot.say("Sorry, the currently authenticated account does not have access to that subreddit")
return
resp_json = resp_json["data"]["children"]
await self.post_menu(ctx, resp_json, page=0, timeout=30)
def subreddit_new(self, ctx, subreddit: str, post_count: int=3):
"""Command for getting subreddit's new posts"""
if post_count <= 0 or post_count > 100:
await self.bot.say("Sorry, I can't do that")
else:
url = "https://oauth.reddit.com/r/{}/new".format(subreddit)
url += "?limit=" + str(post_count)
headers = {
"Authorization": "bearer " + self.access_token,
"User-Agent": "Red-DiscordBotRedditCog/0.1 by /u/palmtree5"
}
async with aiohttp.get(url, headers=headers) as req:
resp_json = await req.json()
if "data" not in resp_json and resp_json["error"] == 403:
await self.bot.say("Sorry, the currently authenticated account does not have access to that subreddit")
return
resp_json = resp_json["data"]["children"]
await self.post_menu(ctx, resp_json, page=0, timeout=30)
def subreddit_top(self, ctx, subreddit: str, post_count: int=3):
"""Command for getting subreddit's top posts"""
if post_count <= 0 or post_count > 100:
await self.bot.say("Sorry, I can't do that")
else:
url = "https://oauth.reddit.com/r/{}/top".format(subreddit)
url += "?limit=" + str(post_count)
headers = {
"Authorization": "bearer " + self.access_token,
"User-Agent": "Red-DiscordBotRedditCog/0.1 by /u/palmtree5"
}
async with aiohttp.get(url, headers=headers) as req:
resp_json = await req.json()
if "data" not in resp_json and resp_json["error"] == 403:
await self.bot.say("Sorry, the currently authenticated account does not have access to that subreddit")
return
resp_json = resp_json["data"]["children"]
await self.post_menu(ctx, resp_json, page=0, timeout=30)
def subreddit_controversial(self, ctx, subreddit: str,
post_count: int=3):
"""Command for getting subreddit's controversial posts"""
if post_count <= 0 or post_count > 100:
await self.bot.say("Sorry, I can't do that")
else:
url =\
"https://oauth.reddit.com/r/{}/controversial".format(subreddit)
url += "?limit=" + str(post_count)
headers = {
"Authorization": "bearer " + self.access_token,
"User-Agent": "Red-DiscordBotRedditCog/0.1 by /u/palmtree5"
}
async with aiohttp.get(url, headers=headers) as req:
resp_json = await req.json()
if "data" not in resp_json and resp_json["error"] == 403:
await self.bot.say("Sorry, the currently authenticated account does not have access to that subreddit")
return
resp_json = resp_json["data"]["children"]
await self.post_menu(ctx, resp_json, page=0, timeout=30)
def _request(self, payload, endpoint):
"""Handles requesting to the API"""
# Format the URL we'll need based on the base_url, and the endpoint we want to hit
url = "{}{}".format(base_url, endpoint)
# Check if our key was added, if it wasn't, add it
key = payload.get('k', self.key)
payload['k'] = key
# Attempt to connect up to our max retries
for x in range(MAX_RETRIES):
try:
async with aiohttp.get(url, headers=self.headers, params=payload) as r:
# If we failed to connect, attempt again
if r.status != 200:
continue
data = await r.json()
return data
# If any error happened when making the request, attempt again
except:
continue
def imdb(message): # Method added by BananaWaffles.
msg = message.content.split()
if apis["MYAPIFILMS_TOKEN"] == "TOKENHERE":
await client.send_message(message.channel, "`This command wasn't configured properly. If you're the owner, edit json/apis.json`")
return False
if len(msg) > 1:
if len(msg[1]) > 1 and len([msg[1]]) < 20:
try:
msg.remove(msg[0])
msg = "+".join(msg)
search = "http://api.myapifilms.com/imdb/title?format=json&title=" + msg + "&token=" + apis["MYAPIFILMS_TOKEN"]
async with aiohttp.get(search) as r:
result = await r.json()
title = result['data']['movies'][0]['title']
year = result['data']['movies'][0]['year']
rating = result['data']['movies'][0]['rating']
url = result['data']['movies'][0]['urlIMDB']
msg = "Title: " + title + " | Released on: " + year + " | IMDB Rating: " + rating + ".\n" + url
await client.send_message(message.channel, msg)
except:
await client.send_message(message.channel, "`Error.`")
else:
await client.send_message(message.channel, "`Invalid search.`")
else:
await client.send_message(message.channel, "`" + settings["PREFIX"] + "imdb [text]`")
def memes(message):
msg = message.content[6:]
msg = msg.split(";")
if apis["IMGFLIP_USERNAME"] == "USERNAMEHERE" or apis["IMGFLIP_PASSWORD"] == "PASSWORDHERE":
await client.send_message(message.channel, "`This command wasn't configured properly. If you're the owner, edit json/apis.json`")
return False
if len(msg) == 3:
if len(msg[0]) > 1 and len([msg[1]]) < 20 and len([msg[2]]) < 20:
try:
search = "https://api.imgflip.com/caption_image?template_id=" + msg[0] + "&username=" + apis["IMGFLIP_USERNAME"] + "&password=" + apis["IMGFLIP_PASSWORD"] + "&text0=" + msg[1] + "&text1=" + msg[2]
async with aiohttp.get(search) as r:
result = await r.json()
if result["data"] != []:
url = result["data"]["url"]
await client.send_message(message.channel, url)
except:
error = result["error_message"]
await client.send_message(message.channel, error)
else:
await client.send_message(message.channel, "`" + settings["PREFIX"] + "meme id;text1;text2 | " + settings["PREFIX"] + "meme help for full list`")
else:
await client.send_message(message.channel, "`" + settings["PREFIX"] + "meme id;text1;text2 | " + settings["PREFIX"] + "meme help for full list`")
def urban(message):
msg = message.content.split()
if len(msg) > 1:
if len(msg[1]) > 1 and len([msg[1]]) < 20:
try:
msg.remove(msg[0])
msg = "+".join(msg)
search = "http://api.urbandictionary.com/v0/define?term=" + msg
async with aiohttp.get(search) as r:
result = await r.json()
if result["list"] != []:
definition = result['list'][0]['definition']
example = result['list'][0]['example']
await client.send_message(message.channel, "Definition: " + definition + "\n\n" + "Example: " + example )
else:
await client.send_message(message.channel, "`Your search terms gave no results.`")
except:
await client.send_message(message.channel, "`Error.`")
else:
await client.send_message(message.channel, "`Invalid search.`")
else:
await client.send_message(message.channel, "`" + settings["PREFIX"] + "urban [text]`")
def gif(message):
msg = message.content.split()
if len(msg) > 1:
if len(msg[1]) > 1 and len([msg[1]]) < 20:
try:
msg.remove(msg[0])
msg = "+".join(msg)
search = "http://api.giphy.com/v1/gifs/search?q=" + msg + "&api_key=dc6zaTOxFJmzC"
async with aiohttp.get(search) as r:
result = await r.json()
if result["data"] != []:
url = result["data"][0]["url"]
await client.send_message(message.channel, url)
else:
await client.send_message(message.channel, "`Your search terms gave no results.`")
except:
await client.send_message(message.channel, "`Error.`")
else:
await client.send_message(message.channel, "`Invalid search.`")
else:
await client.send_message(message.channel, "`" + settings["PREFIX"] + "gif [text]`")
def transferPlaylist(message):
msg = message.attachments[0]
if msg["filename"].endswith(".txt"):
if not dataIO.fileIO("playlists/" + msg["filename"], "check"): #returns false if file already exists
r = await aiohttp.get(msg["url"])
r = await r.text()
data = r.replace("\r", "")
data = data.split()
if isPlaylistValid(data) and isPlaylistNameValid(msg["filename"].replace(".txt", "")):
data = { "author" : message.author.id,
"playlist": data}
dataIO.fileIO("playlists/" + msg["filename"], "save", data)
await client.send_message(message.channel, "`Playlist added. Name: {}`".format(msg["filename"].replace(".txt", "")))
else:
await client.send_message(message.channel, "`Something is wrong with the playlist or its filename. Type " + settings["PREFIX"] + "audio help to read how to format it properly.`")
else:
await client.send_message(message.channel, "`A playlist with that name already exists. Change the filename and resubmit it.`")
def fetch(self):
"""Fetches url of the reporter and returns news.
:returns: Either a list of news or a news.
:rtype: :class:`list` or `~news.models.AbstractNews` implemnetation.
"""
async with aiohttp.get(self.url) as response:
# return nothing if status code is not OK
if response.status != 200:
return None
# make news from the response
items = self.parse(await response.text())
# return a single news if we have only one. return a list of news
# if we have more than a single news.
try:
return (self.make_news(item) for item in items)
except TypeError:
item = items
news = self.make_news(item)
return news
def cmd_modlog(self, message, author, server, option, new_id=None, reason=None):
"""
Usage: {command_prefix}modlog [set | + | - | true | false | yes | no | y | n] <new channel ID> ["reason"]
If the first choice is set, it will change the mod log to the provided channel
If the first choice is anything else, it'll toggle whether the modlog is used or not!
"+, true, yes, y" will enable it and "-, false, no, n" will disable it
"""
if await self.has_roles(message.channel, author, server, command='modlog'):
if option not in ['set', '+', '-', 'true', 'false', 'yes', 'no', 'y', 'n']:
raise CommandError(
'Invalid option "%s" specified, use +, -, true, false, yes, no, set, y or n' % option)
if option in ['set']:
try:
channel = discord.utils.get(server.channels, id=new_id)
if not channel:
int('this')
except:
raise CommandError('Invalid Channel ID: {}'.format(new_id))
self.server_index[server.id][8] = channel.id
elif option in ['+', 'true', 'yes', 'y']:
self.server_index[server.id][10][0] = True
else:
self.server_index[server.id][10][0] = False
await self.write_to_modlog(message, author, server, reason)
def cmd_setannouncements(self, message, author, server, new_id, reason=None):
"""
Usage: {command_prefix}setannouncements <new channel ID> ["reason"]
Sets which channel will be used for announcements / broadcasts relating to RH1-N0
Defaults to default server channel
"""
if await self.has_roles(message.channel, author, server, command='setannouncements'):
try:
channel = discord.utils.get(server.channels, id=new_id)
if not channel:
int('this')
except:
raise CommandError('Invalid Channel ID: {}'.format(new_id))
self.server_index[server.id][17] = channel.id
await self.write_to_modlog(message, author, server, reason)