Compare commits

..

1 Commits
master ... test

Author SHA1 Message Date
Arthur POULET efaf244bb3
XXX 2020-01-19 21:08:02 +01:00
21 changed files with 177 additions and 143 deletions

View File

@ -11,9 +11,9 @@ release:
test:
crystal spec
deps:
shards install --ignore-crystal-version
crystal deps install
deps_update:
shards update --ignore-crystal-version
crystal deps update
deps_opt:
@[ -d lib/ ] || make deps
doc:

View File

@ -1,6 +1,6 @@
# DashBot
A good bot, or a collection of plugins for Crirc network client.
TODO: Write a description here
## Installation
@ -11,23 +11,20 @@ Install ``postgresql``, ``crystal``, and ``crystal-shards``
git clone https://github.com/Meoowww/DashBot
cd DashBot
# Install the libs
shards install
crystal deps install
# Build the project
crystal b -s --release src/DashBot.cr
# Configure the database
psql -U postgres postgres -c "CREATE USER root WITH PASSWORD 'toor' SUPERUSER;"
psql -U postgres postgres -c "CREATE DATABASE dash_bot"
echo "PG_URL=postgres://root:toor@localhost/dash_bot
NETWORK_HOST=chat.freenode.net
NETWORK_PORT=6697
NETWORK_SSL=true
NICKNAME=Dasshyx" > .env
echo "PG_URL=postgres://root:toor@localhost/dash_bot" > .env
# Update the database
./bin/micrate up
# Run the bot
./DashBot
```
## Usage
@ -40,7 +37,7 @@ TODO: Write development instructions here
## Contributing
1. Fork it ( https://git.sceptique.eu/Sceptique/DashBot/fork )
1. Fork it ( https://github.com/Meoowww/DashBot/fork )
2. Create your feature branch (git checkout -b my-new-feature)
3. Commit your changes (git commit -am 'Add some feature')
4. Push to the branch (git push origin my-new-feature)
@ -48,5 +45,5 @@ TODO: Write development instructions here
## Contributors
- [Sceptique](https://git.sceptique.eu/Sceptique) Arthur Poulet - creator, maintainer
- [pouleta](https://github.com/Nephos) Arthur Poulet - creator, maintainer
- [Lucie](https://github.com/Lucie-Dispot) Lucie Dispot - developer

5
config.json Normal file
View File

@ -0,0 +1,5 @@
{
"BasicCommands": {
"enabled": true
}
}

View File

@ -1,34 +1,30 @@
version: 2.0
version: 1.0
shards:
crirc:
git: https://git.sceptique.eu/Sceptique/Crirc
version: 0.5.1+git.commit.1aab6b69c7e9cca6780bc335d7b79739e201f1dd
github: Meoowww/Crirc
commit: 547caf55a8913b62fb536d87108f0da7c697fae7
daemonize:
github: DougEverly/daemonize.cr
commit: 03d7da27fe76ee6b77d47a66984969a308a42027
db:
git: https://github.com/crystal-lang/crystal-db.git
version: 0.10.1
github: crystal-lang/crystal-db
version: 0.5.0
dotenv:
git: https://github.com/gdotdesign/cr-dotenv.git
version: 1.0.0
github: gdotdesign/cr-dotenv
version: 0.1.0
micrate:
git: https://github.com/juanedi/micrate.git
version: 0.10.0
mysql:
git: https://github.com/crystal-lang/crystal-mysql.git
version: 0.13.0
github: juanedi/micrate
version: 0.3.0
pg:
git: https://github.com/will/crystal-pg.git
version: 0.23.1
github: will/crystal-pg
version: 0.14.1
rollable:
git: https://git.sceptique.eu/Sceptique/rollable
version: 1.0.0+git.commit.84ef972fec468d03381a815675b7a906b792458b
sqlite3:
git: https://github.com/crystal-lang/crystal-sqlite3.git
version: 0.18.0
github: Nephos/crystal_rollable
commit: 98590287860e3307db6a7ff72774ab1469d90195

View File

@ -1,21 +1,19 @@
name: DashBot
version: 1.1.0
version: 0.1.0
authors:
- Arthur Poulet <arthur.poulet@mailoo.org>
license: MIT
crystal: 1.0.0
dependencies:
# irc
crirc:
git: https://git.sceptique.eu/Sceptique/Crirc
github: Meoowww/Crirc
branch: master
# dice roll
rollable:
git: https://git.sceptique.eu/Sceptique/rollable
github: Nephos/crystal_rollable
branch: master
# Sql
pg:
@ -29,3 +27,6 @@ dependencies:
# .env file
dotenv:
github: gdotdesign/cr-dotenv
# --daemonize
daemonize:
github: DougEverly/daemonize.cr

View File

@ -2,8 +2,11 @@
require "crirc"
require "rollable"
require "./DashBot/*"
require "./DashBot/plugins/*"
require "yaml"
require "json"
class DashBot
end
# Extention of `String`.
module DashBot::Source
@ -24,28 +27,44 @@ class String
include DashBot::Source
end
module DashBot
module Loader
def fetch_configuration(file)
configuration = File.read(file)
if file.ends_with?(".yml") || file.ends_with?(".yaml")
YAML.parse(configuration)
else
JSON.parse(configuration)
end
end
macro bind_plugins(config, *plugins)
{% for plugin in plugins %}
plugin = Plugins::{{plugin.id}}
plugin_config = Hash(String, String).new
config[{{plugin}}].each { |k, v| plugin_config[k.to_s] = v.to_s }
plugin_instance = plugin.new(plugin_config)
plugin_instance.bind(bot) if plugin_instance.enabled?
{% end %}
end
extend self
end
require "./DashBot/*"
require "./DashBot/plugins/*"
class DashBot
def initialize
@config = Hash(String, Hash(String, String)).new
end
def start
Arguments.new.use
client = Crirc::Network::Client.new(
ip: ENV["NETWORK_HOST"],
port: ENV["NETWORK_PORT"].to_u16,
ssl: ENV["NETWORK_SSL"] == "true",
nick: ENV["NICKNAME"] + "#{rand(1..9)}",
read_timeout: 300_u16,
)
client = Crirc::Network::Client.new(ip: "irc.mozilla.org", port: 6667_u16, ssl: false, nick: "Dasshyx#{rand(1..9)}", read_timeout: 300_u16)
client.connect
client.start do |bot|
Plugins::BasicCommands.bind(bot)
Plugins::UserCommands.bind(bot)
Plugins::AdminCommands.bind(bot)
Plugins::Points.bind(bot)
Plugins::Messages.bind(bot)
Plugins::Reminder.bind(bot)
Plugins::Rpg.bind(bot)
Plugins::Random.bind(bot)
Plugins::Anarchism.bind(bot)
Plugins::TitleReader.bind(bot)
config = Loader.fetch_configuration("config.json")
Loader.bind_plugins(config, "BasicCommands", "UserCommands", "AdminCommands", "Points", "Messages", "Reminder", "Rpg", "Random", "Anarchism"
bot.on_ready do
bot.join (ARGV.empty? ? ["#equilibre"] : ARGV).map { |chan| Crirc::Protocol::Chan.new(chan) }
@ -55,21 +74,19 @@ module DashBot
begin
m = bot.gets
break if m.nil?
STDERR.puts "[#{Time.utc}] #{m}"
STDERR.puts "[#{Time.now}] #{m}"
spawn { bot.handle(m.as(String)) }
rescue IO::TimeoutError
rescue IO::Timeout
puts "Nothing happened..."
end
end
end
end
extend self
end
loop do
begin
DashBot.start
DashBot.new.start
rescue err
STDERR.puts err
STDOUT.puts err

View File

@ -7,7 +7,7 @@ class DashBot::Arguments
@out = "/var/log/dash_bot/chans.log"
def use
OptionParser.parse do |parser|
OptionParser.parse! do |parser|
parser.banner = "Usage: DashBot [arguments]"
parser.on("-e error", "--errors=PATH", "Specifies the path of the error log") { |path|
@err = path
@ -18,8 +18,8 @@ class DashBot::Arguments
Dir.mkdir(File.dirname(@out)) if !Dir.exists?(File.dirname(@out))
}
parser.on("-h", "--help", "Show this help") { puts parser; exit }
# parser.on("-d", "--daemonize", "Run in background as daemon") { @daemonize = true }
parser.on("-d", "--daemonize", "Run in background as daemon") { @daemonize = true }
end
# Daemonize.daemonize(stdout: @out, stderr: @err, stdin: "/dev/null") if @daemonize
Daemonize.daemonize(stdout: @out, stderr: @err, stdin: "/dev/null") if @daemonize
end
end

View File

@ -4,16 +4,13 @@ require "pg"
# Load env
Dotenv.load
module DashBot
module DashBot::Database
DB = PG.connect(ENV["PG_URL"])
extend self
module Database
extend self
def user_exists?(name)
n = DB.query_one("SELECT COUNT(*) AS count FROM users WHERE name=$1", [name], as: {Int64})
raise "User \"#{name}\" registered #{n} times !!" if n > 1
n == 1
end
def user_exists?(name)
n = DB.query_one("SELECT COUNT(*) AS count FROM users WHERE name=$1", [name], as: {Int64})
raise "User \"#{name}\" registered #{n} times !!" if n > 1
n == 1
end
end

38
src/DashBot/plugin.cr Normal file
View File

@ -0,0 +1,38 @@
class DashBot::Plugin
@configuration : Hash(String, String)
# def bind(bot)
def initialize(config : Hash(String, String))
@configuration = { "enabled" => "false" }
config.each { |k, v| @configuration[k] = v }
end
def initialize
@configuration = { "enabled" => "false" }
end
def enable
@configuration["enabled"] = "true"
end
def disable
@configuration["enabled"] = "false"
end
def enabled?
@configuration["enabled"] == "true"
end
def disabled?
!enabled?
end
def configure(key : String, value : String)
@configuration[key] = value
end
def configuration(key : String)
@configuration[key]? || ""
end
end

View File

@ -1,7 +1,7 @@
module DashBot::Plugins::Anarchism
extend self
@@is_op = false
@@current_chan : Crirc::Protocol::Chan|Nil = nil
@@current_chan : Crirc::Protocol::Chan | Nil = nil
@@user_list = Array(Crirc::Protocol::User).new
def bind(bot)

View File

@ -1,6 +1,6 @@
module DashBot::Plugins::BasicCommands
extend self
require "../plugin"
class DashBot::Plugins::BasicCommands < DashBot::Plugin
WHAT = %w(ce que tu dis n'a aucun sens)
def bind(bot)
@ -8,10 +8,10 @@ module DashBot::Plugins::BasicCommands
if msg.source == bot.nick.to_s
bot.reply msg, "Welcome everypony, what's up ? :)"
else
STDERR.puts "[#{Time.utc}] #{msg.source.source_id} joined the chan"
STDERR.puts "[#{Time.now}] #{msg.source.source_id} joined the chan"
end
end.on("PING") do |msg|
STDERR.puts "[#{Time.utc}] PONG :#{msg.message}"
STDERR.puts "[#{Time.now}] PONG :#{msg.message}"
bot.pong(msg.message)
end.on("PRIVMSG", message: /^!ping/, doc: {"!ping", "!ping"}) do |msg|
bot.reply msg, "pong #{msg.source.source_id}"

View File

@ -16,7 +16,7 @@ module DashBot::Plugins::Messages
id = match.as(Regex::MatchData)[1]
message = match.as(Regex::MatchData)[2]
DB.exec "INSERT INTO messages (author, dest, content, created_at)
VALUES ($1, $2, $3, NOW())", msg.source.source_id, id, message
VALUES ($1, $2, $3, NOW())", [msg.source.source_id, id, message]
# bot.privmsg User.new(msg.source.source_id), "Message sent to \"#{id}\""
bot.reply msg, "Message sent to \"#{id}\""
end
@ -26,12 +26,12 @@ module DashBot::Plugins::Messages
bot.on("PRIVMSG", message: /^!read$/, doc: {"!read", "!read read the inbox"}) do |msg, match|
m = DB.query_one(
"SELECT id, author, dest, content, created_at, read_at FROM messages WHERE read_at IS NULL AND dest = $1
ORDER BY created_at ASC LIMIT 1", msg.source.source_id, as: {Int32, String, String, String, Time, Time?}) rescue nil
ORDER BY created_at ASC LIMIT 1", [msg.source.source_id], as: {Int32, String, String, String, Time, Time?}) rescue nil
if m
message = {id: m[0], author: m[1], dest: m[2], content: m[3], created_at: m[4], read_at: m[5]}
# user = User.new(msg.source.source_id)
date = message[:created_at]
if Time.utc.to_s("%j") == date.to_s("%j")
if Time.now.to_s("%j") == date.to_s("%j")
date = date.to_s("%H:%M:%S")
else
date = date.to_s("%B, %d at %H:%M:%S")
@ -46,7 +46,7 @@ module DashBot::Plugins::Messages
def bind_signal(bot)
bot.on("JOIN") do |msg, _|
count = DB.query_one("SELECT COUNT(*) FROM messages WHERE read_at IS NULL and DEST = $1", msg.source.source_id, as: {Int64})
count = DB.query_one("SELECT COUNT(*) FROM messages WHERE read_at IS NULL and DEST = $1", [msg.source.source_id], as: {Int64})
bot.reply msg, "#{msg.source.source_id}, you have #{count} messages" if count > 0
end
end

View File

@ -10,8 +10,10 @@ module DashBot::Plugins::Points
def bind_add(bot)
bot.on("PRIVMSG", message: /^!p +([[:graph:]]+) +([[:graph:]]+)/, doc: {"!p", "!p type someone"}) do |msg, match|
match = match.as Regex::MatchData
DB.exec "INSERT INTO points (assigned_to, assigned_by, type, created_at) VALUES ($1, $2, $3, NOW())", match[2], msg.source.source_id, match[1].downcase
n = DB.query_one("SELECT COUNT(*) FROM points WHERE assigned_to = $1 AND type = $2", match[2], match[1].downcase, as: {Int64})
DB.exec "INSERT INTO points (assigned_to, assigned_by, type, created_at)
VALUES ($1, $2, $3, NOW())", [match[2], msg.source.source_id, match[1].downcase]
n = DB.query_one("SELECT COUNT(*) FROM points WHERE assigned_to = $1 AND type = $2",
[match[2], match[1].downcase], as: {Int64})
bot.reply msg, "#{match[2]} has now #{n} point#{n > 1 ? "s" : ""} #{match[1]}"
end
end

View File

@ -24,13 +24,13 @@ module DashBot::Plugins::Reminder
bot.on("PRIVMSG", message: /^!remindme$/, doc: {"!remindme", "!remindme"}) do |msg, match|
messages = DB.query_all(
"SELECT id, author, remind_time, content, created_at, checked_at, read_at FROM reminders WHERE read_at IS NULL AND author = $1",
msg.source.source_id, as: {Int32, String, Time, String, Time, Time?, Time?}) rescue nil
[msg.source.source_id], as: {Int32, String, Time, String, Time, Time?, Time?}) rescue nil
if messages
messages.each do |m|
message = {id: m[0], author: m[1], remind_time: m[2], content: m[3], created_at: m[4], read_at: m[5]}
if message[:remind_time] < Time.utc
if message[:remind_time] < Time.utc_now
date = message[:remind_time].to_local
if Time.utc.to_s("%j") == date.to_s("%j")
if Time.now.to_s("%j") == date.to_s("%j")
date = date.to_s("%H:%M:%S")
else
date = date.to_s("%B, %d at %H:%M:%S")
@ -51,7 +51,7 @@ module DashBot::Plugins::Reminder
if messages
messages.each do |m|
message = {id: m[0], author: m[1], remind_time: m[2], content: m[3], created_at: m[4], read_at: m[5]}
if message[:remind_time] < Time.utc
if message[:remind_time] < Time.utc_now
# TODO: fix this so it finds the user's nickname and sends it to it instead
bot.privmsg Crirc::Protocol::User.new(message[:author]), "You have a new reminder"
DB.exec "UPDATE reminders SET checked_at = NOW() WHERE id = $1", [message[:id]]
@ -64,7 +64,7 @@ module DashBot::Plugins::Reminder
def bind_signal(bot)
bot.on("JOIN") do |msg, _|
count = DB.query_one("SELECT COUNT(*) FROM reminders WHERE read_at IS NULL and checked_at IS NOT NULL and author = $1", msg.source.source_id, as: {Int64})
count = DB.query_one("SELECT COUNT(*) FROM reminders WHERE read_at IS NULL and checked_at IS NOT NULL and author = $1", [msg.source.source_id], as: {Int64})
bot.reply msg, "#{msg.source.source_id}, you have #{count} reminders" if count > 0
end
end

View File

@ -13,7 +13,7 @@ module DashBot::Plugins::Rpg::Music
bot.on("PRIVMSG", message: /^!music +add +([[:graph:]]+) +([[:graph:]]+)/) do |msg, match|
msg_match = match.as Regex::MatchData
DB.exec("INSERT INTO musics (owner, category, url, created_at)
VALUES ($1, $2, $3, NOW())", msg.source.source_id, msg_match[1], msg_match[2])
VALUES ($1, $2, $3, NOW())", [msg.source.source_id, msg_match[1], msg_match[2]])
bot.reply msg, "Music successfully added."
end
end
@ -21,12 +21,12 @@ module DashBot::Plugins::Rpg::Music
def bind_del_music(bot)
bot.on("PRIVMSG", message: /^!music +delete +([[:graph:]]+) +([[:graph:]]+)/) do |msg, match|
msg_match = match.as Regex::MatchData
musics = DB.query_all("SELECT url FROM musics WHERE category = $1", msg_match[1], as: {String})
musics = DB.query_all("SELECT url FROM musics WHERE category = $1", [msg_match[1]], as: {String})
if msg_match[2].to_i > musics.size
bot.reply msg, "This music doesn't exist."
else
DB.exec("DELETE FROM musics WHERE url = $1", musics[msg_match[2].to_i - 1]["url"])
DB.exec("DELETE FROM musics WHERE url = $1", [musics[msg_match[2].to_i - 1]["url"]])
bot.reply msg, "Music successfully deleted."
end
end
@ -41,7 +41,7 @@ module DashBot::Plugins::Rpg::Music
bot.on("PRIVMSG", message: /^!music +(?:list|ls) +([[:graph:]]+)/) do |msg, match|
msg_match = match.as Regex::MatchData
urls = DB.query_all("SELECT url FROM musics WHERE category = $1 LIMIT 5", msg_match[1], as: {String}).join(", ")
urls = DB.query_all("SELECT url FROM musics WHERE category = $1 LIMIT 5", [msg_match[1]], as: {String}).join(", ")
bot.reply msg, "The following musics are present in the category #{msg_match[1]}: #{urls}"
end
end
@ -50,14 +50,14 @@ module DashBot::Plugins::Rpg::Music
# Select a random music
bot.on("PRIVMSG", message: /^!music play +([[:graph:]]+) +$/) do |msg, match|
msg_match = match.as Regex::MatchData
musics = DB.query_all("SELECT url FROM musics WHERE category = $1", msg_match[1], as: {String})
musics = DB.query_all("SELECT url FROM musics WHERE category = $1", [msg_match[1]], as: {String})
bot.reply msg, "#{musics.sample}"
end
# Select a specific music
bot.on("PRIVMSG", message: /^!music play +([[:graph:]]+) +([[:graph:]]+)/) do |msg, match|
msg_match = match.as Regex::MatchData
musics = DB.query_all("SELECT url FROM musics WHERE category = $1", msg_match[1], as: {String})
musics = DB.query_all("SELECT url FROM musics WHERE category = $1", [msg_match[1]], as: {String})
if msg_match[2].to_i > musics.size
bot.reply msg, "Error: this track doesn't exist (yet)."
else

View File

@ -25,7 +25,7 @@ module DashBot::Plugins::Rpg::Roll
# check if name already exists
n = DB.query_one("SELECT COUNT(*) FROM dies WHERE name = $1 AND owner = $2",
msg_match[1], msg.source.source_id, as: {Int64})
[msg_match[1], msg.source.source_id], as: {Int64})
if n > 0
bot.reply msg, "Error: #{msg_match[1]} already exists. Remove it or use another name."
@ -44,7 +44,7 @@ module DashBot::Plugins::Rpg::Roll
msg_match = match.as Regex::MatchData
begin
roll = DB.query_one("SELECT roll FROM dies WHERE name = $1 AND owner = $2",
msg_match[1], msg.source.source_id, as: {String})
[msg_match[1], msg.source.source_id], as: {String})
rescue
bot.reply msg, "Roll #{msg_match[1]} does not exist."
next
@ -62,7 +62,7 @@ module DashBot::Plugins::Rpg::Roll
match = match.as Regex::MatchData
limit = (match[2]? || "8").to_i
all_rolls = DB.query_all("SELECT owner, roll FROM dies WHERE name = $1",
match[1], as: {String, String})
[match[1]], as: {String, String})
rolls = all_rolls.shift(limit)
bot.reply msg, "#{all_rolls.size} rolls will not be launch." if !all_rolls.empty?

View File

@ -1,17 +0,0 @@
require "http/client"
require "xml"
module DashBot::Plugins::TitleReader
extend self
def bind(bot)
bot.on("PRIVMSG", message: /(http[^ ]+)/, doc: {"any url", "look a this http://url/"}) do |msg, match|
match = match.as Regex::MatchData
url = match[1]
response = HTTP::Client.get url
xml = XML.parse response.body
title_node = xml.xpath_node("//title")
bot.reply msg, "(#{title_node.text})" if title_node
end
end
end

View File

@ -20,9 +20,9 @@ module DashBot::Plugins::UserCommands
match = match.as Regex::MatchData
if user_exists? match[1]
groups = DB.query_all("SELECT groups.id AS id, groups.name AS name FROM groups
INNER JOIN users ON groups.user_name = users.name WHERE users.name = $1", match[1], as: {Int32, String})
INNER JOIN users ON groups.user_name = users.name WHERE users.name = $1", [match[1]], as: {Int32, String})
if idx = groups.index { |e| e[1] == match[2] }
DB.exec "DELETE FROM groups WHERE id = $1", groups[idx][0]
DB.exec "DELETE FROM groups WHERE id = $1", [groups[idx][0]]
bot.reply msg, "The user \"#{match[1]}\" has lost the group \"#{match[2]}\""
else
bot.reply msg, "The user \"#{match[1]}\" does not belongs to the group \"#{match[2]}\""
@ -38,7 +38,7 @@ module DashBot::Plugins::UserCommands
match = match.as Regex::MatchData
if user_exists? match[1]
groups = DB.query_all("SELECT groups.name AS name FROM groups
INNER JOIN users ON groups.user_name = users.name WHERE users.name = $1", match[1], as: {String})
INNER JOIN users ON groups.user_name = users.name WHERE users.name = $1", [match[1]], as: {String})
groups = groups.join(", ")
bot.reply msg, "User \"#{match[1]}\" has the groups : #{groups}"
else
@ -52,7 +52,7 @@ module DashBot::Plugins::UserCommands
next if !authorize! bot, msg
match = match.as Regex::MatchData
if user_exists? match[1]
DB.exec "INSERT INTO groups (user_name, name) VALUES ($1, $2)", match[1], match[2]
DB.exec "INSERT INTO groups (user_name, name) VALUES ($1, $2)", [match[1], match[2]]
bot.reply msg, "The user \"#{match[1]}\" has gained the group \"#{match[2]}\""
else
bot.reply msg, "User \"#{match[1]}\" not registered"
@ -66,9 +66,9 @@ module DashBot::Plugins::UserCommands
bot.reply msg, "Cannot register \"#{msg.source.source_id}\" twice"
else
bot.reply msg, "Register \"#{msg.source.source_id}\""
is_admin = DB.query_one("SELECT COUNT(*) FROM users", as: {Int64}) == 0
DB.exec "INSERT INTO users (name) VALUES ($1)", msg.source.source_id
DB.exec "INSERT INTO groups (user_name, name) VALUES ($1, $2)", msg.source.source_id, is_admin ? "admin" : "default"
is_admin = DB.query_one("SELECT COUNT(*) FROM users", [] of Int64, as: {Int64}) == 0
DB.exec "INSERT INTO users (name) VALUES ($1)", [msg.source.source_id]
DB.exec "INSERT INTO groups (user_name, name) VALUES ($1, $2)", [msg.source.source_id, is_admin ? "admin" : "default"]
end
end
end

View File

@ -1,21 +1,19 @@
module DashBot
module Rights
def authorized?(msg, group = "admin")
n = DB.query_one("SELECT COUNT(*) FROM groups
INNER JOIN users ON groups.user_name = users.name WHERE groups.name = $1 AND users.name = $2",
group, msg.source.source_id, as: {Int64})
n == 1
end
module DashBot::Rights
def authorized?(msg, group = "admin")
n = DB.query_one("SELECT COUNT(*) FROM groups
INNER JOIN users ON groups.user_name = users.name WHERE groups.name = $1 AND users.name = $2",
[group, msg.source.source_id], as: {Int64})
n == 1
end
def authorized?(msg, groups : Array(String))
groups.any? { |group| authorized? msg, group }
end
def authorized?(msg, groups : Array(String))
groups.any? { |group| authorized? msg, group }
end
def authorize!(bot, msg : Crirc::Protocol::Message, group = "admin", reply = "Unauthorized")
return true if authorized? msg, group
bot.reply msg, reply
false
end
def authorize!(bot, msg : Crirc::Protocol::Message, group = "admin", reply = "Unauthorized")
return true if authorized? msg, group
bot.reply msg, reply
false
end
extend self

View File

@ -1,6 +1,6 @@
struct Time
def self.adaptive_parse(txt)
t = Time.utc
t = Time.now
parsing_formats = {
"%R %-d/%m/%Y" => " #{t.day}/#{t.month}/#{t.year}",
"%T %-d/%m/%Y" => " #{t.day}/#{t.month}/#{t.year}",
@ -18,8 +18,8 @@ struct Time
parsing_formats.each do |f, v|
begin
t = Format.new(f).parse(txt + v).to_utc
t += 365.days if t < Time.utc
t = Format.new(f, Time::Kind::Local).parse(txt + v).to_utc
t += 365.days if t < Time.now
return t
rescue
end

View File

@ -1,3 +1,3 @@
module DashBot
class DashBot
VERSION = "0.1.0"
end