This repository has been archived by the owner on Mar 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
randibooru.py
169 lines (141 loc) · 7.28 KB
/
randibooru.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import discord
import asyncio
import random
import derpibooru
import configparser
import os.path
import sys
import traceback
import logging
log = logging.getLogger('randibooru')
formatter = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
log.addHandler(console_handler)
config = configparser.ConfigParser()
if os.path.isfile('./config.ini'):
config.read('./config.ini')
else:
config['Command'] = {'Prefix': '!',
'Name': 'rb'}
config['API keys'] = {'Derpibooru': '',
'Discord': ''}
config['Logging'] = {'Level': 'INFO'}
config['Other'] = {'ImagesPerRequest': 50}
with open('./config.ini', 'w') as cfgfile:
config.write(cfgfile)
log.info('Config file generated!')
log.info('Edit config.ini before starting Randibooru.')
sys.exit(1)
level = logging.getLevelName(config.get('Logging', 'Level', fallback = 'INFO'))
try:
log.setLevel(level = level)
except ValueError:
log.setLevel(level = logging.INFO)
NUM_TAGS_IN_EMBED = 10
MAX_TAG_STR_LEN = 100
DISCORD_API_TOKEN = config.get('API keys', 'Discord')
DERPIBOORU_API_TOKEN = config.get('API keys', 'Derpibooru')
COMMAND_PREFIX = config.get('Command', 'Prefix', fallback = '!')
COMMAND_NAME = config.get('Command', 'Name', fallback = 'rb')
COMMAND = COMMAND_PREFIX + COMMAND_NAME
client = discord.Client()
helpgame = discord.Game(name = COMMAND_PREFIX + COMMAND_NAME + " <derpi query>", url = "", type = 0)
@client.event
async def on_ready():
log.info('Logged in as ' + client.user.name + ' (' + client.user.id + ')')
log.info('Use this link to invite me to your server: ' + discord.utils.oauth_url(client.user.id, permissions = discord.Permissions(permissions = 19456)))
await client.change_presence(game = helpgame, afk = False)
@client.event
async def on_error(event, *args, **kwargs):
log.error('Exception occurred in ' + event, exc_info = True)
@client.event
async def on_server_join(server):
general = server.default_channel
log.info('Joined server ' + server.name + ' (' + server.id + ')')
if server.me.permissions_in(general).send_messages:
log.debug('Able to post messages in general channel. Sending welcome message...')
await client.send_message(general, "**Hey there!** I'm Randibooru! I pull random images from Derpibooru with an optional Derpibooru query.\n"
+ "To get a random image, simply type `" + COMMAND + "` in chat, and I'll try to respond. You can optionally follow `" + COMMAND + "` with a Derpibooru query (info here: https://derpibooru.org/search/syntax), and I'll only pull images that match it.\n"
+ "Have fun!\n\n"
+ "*Made with <3 by Bytewave (https://github.com/BytewaveMLP/randibooru)*\n"
+ "Join my Discord server! https://discord.gg/AukVbRR\n\n"
+ "**NOTE:** I will refuse to post images tagged with `explicit` in non-NSFW channels!")
@client.event
async def on_server_remove(server):
log.info('Removed from server ' + server.name + ' (' + server.id + ')')
@client.event
async def on_message(message):
if (message.content == COMMAND) or message.content.startswith(COMMAND + " ") and not message.author.bot:
requester = message.author
query = message.content[(len(COMMAND) + 1):].strip() # Strip command from message text
log_user_str = 'from ' + requester.name + ' (' + requester.id + ')' + (' with query ' + query if query != '' else '')
log.info('Request received ' + log_user_str)
await client.send_typing(message.channel)
response_str = requester.mention + (' (query: `' + query + '`)' if query != '' else '')
search = derpibooru.Search().key(DERPIBOORU_API_TOKEN).sort_by(derpibooru.sort.RANDOM).limit(int(config.get('Other', 'ImagesPerRequest', fallback = '50'))) # DerPyBooru searching
result = None
if not message.channel.is_private:
log.debug('Request ' + log_user_str + ' in channel ' + message.channel.name + ' (' + message.channel.id + ')')
if message.channel.name != 'nsfw' and not message.channel.name.startswith('nsfw-'):
log.debug('Request ' + log_user_str + ' was sent in a SAFE channel - injecting -explicit into query')
search = search.query(query, '-explicit')
results = list(search)
if len(results) == 0:
log.info('No SFW results found for request ' + log_user_str)
await client.send_message(message.channel, response_str + ' - *No safe-for-work images found.*')
return
for potential in results:
if 'explicit' not in potential.tags:
result = potential
break
log.debug('Skipping unsuitable image ' + potential.url + ' for request ' + log_user_str)
else:
log.debug('Request ' + log_user_str + ' was sent in an NSFW channel')
search = search.query(query)
results = list(search)
if len(results) == 0:
log.info('No results found for request ' + log_user_str)
await client.send_message(message.channel, response_str + ' - *No images found.*')
return
result = random.choice(results)
if result is None:
log.info('Couldn\'t find any safe images to post for request ' + log_user_str)
await client.send_message(message.channel, response_str + " - *I couldn't find any safe images! Try again, or call me in an NSFW channel for `explicit` images!*")
return
else:
log.debug('Request ' + log_user_str + ' is a PM')
search = search.query(query)
results = list(search)
if len(results) == 0:
log.info('No results found for request ' + log_user_str)
await client.send_message(message.channel, response_str + ' - *No images found.*')
return
result = random.choice(results)
log.info('Found suitable result ' + result.url + ' for request ' + log_user_str)
if len(result.tags) > NUM_TAGS_IN_EMBED:
log.debug('Limiting displayed tags to ' + str(NUM_TAGS_IN_EMBED) + ' for request ' + log_user_str + ' to keep Discord from yelling at us')
tags = ", ".join(result.tags[:NUM_TAGS_IN_EMBED]) + "..."
else:
tags = ", ".join(result.tags)
if len(tags) > MAX_TAG_STR_LEN:
tags = tags[:MAX_TAG_STR_LEN] + "..."
color = random.randint(0, 16777215)
em = discord.Embed(title = "Derpibooru URL", url = result.url, color = color)
em.set_author(name = "Uploaded by: " + result.uploader, url = ("https://derpibooru.org/profiles/" + result.uploader) if result.uploader != "Background Pony" else discord.Embed.Empty)
em.set_image(url = result.representations['large'])
em.add_field(name = "Tags", value = tags, inline = False)
em.add_field(name = "Score", value = "{score} (+{upvotes}/-{downvotes})".format(score = result.score, upvotes = result.upvotes, downvotes = result.downvotes), inline = True)
em.add_field(name = "Favorites", value = result.faves, inline = True)
em.set_footer(text = "Randibooru - Made with <3 by Bytewave", icon_url = "https://i.imgur.com/3uHsFKL.jpg")
log.debug('Sending embed for request ' + log_user_str)
try:
await client.send_message(message.channel, response_str, embed = em)
except discord.errors.HTTPException as err:
log.error('HTTPException occurred while serving request ' + log_user_str + ' - ' + str(err))
await client.send_message(message.channel, response_str + ' - *An internal error occurred while processing your request. Please try again.*')
log.info('Randibooru bot starting...')
try:
client.run(DISCORD_API_TOKEN)
except:
log.critical('An error occurred while starting Randibooru', exc_info = True)