# DataBase handler module module Players def self.list DB["select * from Players"].all end def self.rm_player(username) DB["delete from Players where username = ?", username].delete != 0 end def self.mk_player(username, email, pass) raise ArgumentError, "Email format is wrong!" unless email.match?(/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/) raise ArgumentError, "Username must be at least 4 characters long and of valid format." unless username.match?(/\A[a-zA-Z][a-zA-Z0-9_.-]+\z/) && username.length >= 4 raise ArgumentError, "Password must be at least 8 characters and of valid format." unless pass.match?(/\A[a-zA-Z0-9_.!?@#$%^&*()+=-]+\z/) && pass.length >= 8 digest = XXhash.xxh32(pass, 1234) code = CODE_ENV == :prod ? Array.new(24) { ALPHANUM.sample }.join : "!" DB[ "insert into Players (username, digest, email, activation_code) values (?, ?, ?, ?)", username, digest, email, code ].insert send_email(:new, email, username, code) if CODE_ENV == :prod [200, "Successfully signed up!"] rescue ArgumentError => e [400, e.message] rescue Sequel::UniqueConstraintViolation [400, "Account already exists with this username or username!"] end def self.verify(code) DB["update Players set activation_code = ? where activation_code = ?", "!", code].update != 0 end def self.unverified DB["select * from Players where activation_code <> ?", "!"].all end def self.pass_req(email) return unless self[email] code = Array.new(24) { ALPHANUM.sample }.join DB["update Players set new_pass_code = ? where email = ?", code, email].update send_email(:pass_req, email, code) end def self.pass_reset(new_pass, code) digest = XXhash.xxh32(new_pass, 1234) DB["update Players set digest = ?, new_pass_code = ? where new_pass_code = ?", digest, "", code].update != 0 end def self.[](username) DB["select * from Players where username = ?", username].first end def self.[]=(username, data) DB["update Players set data = ? where username = ?", data, username].update end def self.authorized?(username, pass) digest = XXhash.xxh32(pass, 1234) player = self[username] player && player[:digest].to_i == digest.to_i ? player : false end def self.verified?(username) player = self[username] Logger.log "Verified: #{player.inspect}\n" player && player[:activation_code] == "!" end Thread.new do loop do unverified.each do |player| rm_player(player[:username]) if player[:created_at] + 24 * 60 * 60 < Time.now end rescue StandardError => e Logger.log "Thread error: #{e.message}\n" ensure sleep 60 * 60 end end end