forked from Humblemonk/DiceMaiden
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdice_maiden.rb
executable file
·193 lines (171 loc) · 6.52 KB
/
dice_maiden.rb
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# Dice bot for Discord
# Author: Humblemonk
# Version: 7.2.0
# Copyright (c) 2017. All rights reserved.
# !/usr/bin/ruby
# If you wish to run a single instance of this bot, please follow the "Manual Install" section of the readme!
require_relative 'dice_maiden_logic'
require_relative 'earthdawn_logic'
require 'discordrb'
require 'dicebag'
require 'dotenv'
require 'rest-client'
require 'sqlite3'
Dotenv.load
@total_shards = ENV['SHARD'].to_i
# Add API token
@bot = Discordrb::Bot.new token: ENV['TOKEN'], num_shards: @total_shards, shard_id: ARGV[0].to_i,
intents: %i[servers server_messages direct_messages], ignore_bots: true, fancy_log: true
@bot.gateway.check_heartbeat_acks = false
@shard = ARGV[0].to_i
@launch_option = ARGV[1].to_s
@prefix = ''
@check = ''
@request_option = false
# open connection to sqlite db and set timeout to 10s if the database is busy
if @launch_option == 'lite'
# do nothing
else
$db = SQLite3::Database.new 'main.db'
$db.busy_timeout = (10_000)
end
mutex = Mutex.new
@bot.message do |event|
# Locking the thread to prevent messages going to the wrong server
mutex.lock
begin
# handle !dm <command>
next if check_server_options(event) == true
# check the server request options
check_request_option(event)
# check what prefix the server should be using
check_prefix(event)
# check if input is even valid
next if input_valid(event) == false
@input = alias_input_pass(event.content) # Do alias pass as soon as we get the message
@simple_output = false
@wng = false
@dh = false
@do_tally_shuffle = false
@ed = false
check_roll_modes
next if @ed && !replace_earthdawn(event)
@roll_set = nil
next unless roll_sets_valid(event)
if @input =~ /^\s*d/
roll_to_one = @input.lstrip
roll_to_one.prepend('1')
@input = roll_to_one
end
@roll = @input
@check = @prefix + @roll
@comment = ''
@test_status = ''
# check user
check_user_or_nick(event)
# check for comment
check_comment
# check for modifiers that should apply to everything
check_universal_modifiers
# Check for dn
dnum = @input.scan(/dn\s?(\d+)/).first.join.to_i if @input.match?(/^(1dn)\d+/i)
# Check for correct input
if @roll.match?(/\dd\d/i)
event.channel.start_typing
next if check_roll(event) == true
# Check for wrath roll
check_wrath
# Grab dice roll, create roll, grab results
if @roll_set.nil?
next if do_roll(event) == true
else
@roll_set_results = ''
@error_check_roll_set = ''
roll_count = 0
error_encountered = false
while roll_count < @roll_set.to_i
if do_roll(event) == true
error_encountered = true
break
end
@tally = alias_output_pass(@tally)
if @simple_output == true
@roll_set_results << "#{@dice_result}\n"
else
@error_check_roll_set << "#{@dice_result}\n"
@roll_set_results << "`#{@tally}` #{@dice_result}\n"
end
roll_count += 1
end
next if error_encountered
log_roll(event) if @launch_option == 'debug'
if @comment.to_s.empty? || @comment.to_s.nil?
event.respond "#{@user} Rolls:\n#{@roll_set_results}"
else
event.respond "#{@user} Rolls:\n#{@roll_set_results} Reason: `#{@comment}`"
end
next
end
# Output aliasing
@tally = alias_output_pass(@tally)
# Grab event user name, server name and timestamp for roll and log it
log_roll(event) if @launch_option == 'debug'
# Print dice result to Discord channel
@has_comment = [email protected]_s.empty? && [email protected]_s.nil?
if check_wrath == true
respond_wrath(event, dnum)
else
event.respond build_response
check_fury(event)
end
end
next if check_donate(event) == true
next if check_help(event) == true
next if check_bot_info(event) == true
next if check_purge(event) == false
rescue StandardError => e ## The worst that should happen is that we catch the error and return its message.
e.message = 'NIL MESSAGE!' if e.message.nil?
# Simplify roll and send it again if we error out due to character limit
if (e.message.include? 'Message over the character limit') || (e.message.include? 'Invalid Form Body')
if @roll_set.nil?
event.respond "#{@user} Roll #{@dice_result} Reason: `Simplified roll due to character limit`"
else
event.respond "#{@user} Rolls:\n#{@error_check_roll_set}Reason: `Simplified roll due to character limit`"
end
elsif (e.message.include? "undefined method `join' for nil:NilClass") || (e.message.include? "The bot doesn't have the required permission to do this!") || (e.message.include? '500: Internal Server Error')
time = Time.now.getutc
File.open('dice_rolls.log', 'a') { |f| f.puts "#{time} ERROR: #{e.message}" }
else
event.respond('Unexpected exception thrown! (' + e.message + ")\n\nPlease drop us a message in the #support channel on the dice maiden server, or create an issue on Github.")
end
end
mutex.unlock
end
if @launch_option == 'lite'
@bot.run
else
@bot.run :async
# Sleep until bot is ready and then set listening status
sleep(1) until @bot.ready
@bot.update_status('online', '!roll', nil, since = 0, afk = false, activity_type = 2)
# Check every 5 minutes and log server count
loop do
sleep 300
time = Time.now.getutc
if @bot.connected? == true
server_parse = @bot.servers.count
$db.execute "update shard_stats set server_count = #{server_parse}, timestamp = CURRENT_TIMESTAMP where shard_id = #{@shard}"
File.open('dice_rolls.log', 'a') { |f| f.puts "#{time} Shard: #{@shard} Server Count: #{server_parse}" }
else
$db.execute "update shard_stats set server_count = 0, timestamp = CURRENT_TIMESTAMP where shard_id = #{@shard}"
File.open('dice_rolls.log', 'a') { |f| f.puts "#{time} Shard: #{@shard} bot not ready!" }
# Bot died and cant connect to Discord. Kill the bot and have eye restart it
exit!
end
# Limit HTTP POST to shard 0. We do not need every shard hitting the discordbots API
next unless @shard == 0
servers = $db.execute 'select sum(server_count) from shard_stats;'
RestClient.post('https://top.gg/api/bots/377701707943116800/stats',
{ "shard_count": @total_shards, "server_count": servers.join.to_i }, 'Authorization': ENV['API'], 'Content-Type': :json)
end
end