Compare commits
No commits in common. "master" and "v0" have entirely different histories.
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -1,10 +1,4 @@
|
||||||
*.swp
|
*.swp
|
||||||
*~
|
*~
|
||||||
*.log
|
.log
|
||||||
*.sqlite3
|
plugins/logger_user.yml
|
||||||
|
|
||||||
old/
|
|
||||||
|
|
||||||
modules_config.yml
|
|
||||||
plugins/log_user.yml
|
|
||||||
|
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
# Database Extension
|
|
||||||
|
|
||||||
## Plugin Database Extension
|
|
||||||
|
|
||||||
You can configure a database to store a large amount of volatiles informations,
|
|
||||||
like the users rights, etc.
|
|
||||||
To do it, there is an extension, ready to be used.
|
|
||||||
|
|
||||||
### 1. configure the database access
|
|
||||||
|
|
||||||
for exemple, in the ``modules_config.yml``:
|
|
||||||
```yaml
|
|
||||||
plugin:
|
|
||||||
database:
|
|
||||||
adapter: postgres
|
|
||||||
host: localhost
|
|
||||||
port: 5432
|
|
||||||
user: root
|
|
||||||
password: toor
|
|
||||||
database: botpop_db
|
|
||||||
```
|
|
||||||
|
|
||||||
*note: you can also configure it in a specific database file.
|
|
||||||
In these case, adapt the following code.*
|
|
||||||
|
|
||||||
Then, in you plugin, add the following code:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
class Plugin < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
include Botpop::Plugin::Database # include the extension
|
|
||||||
|
|
||||||
...
|
|
||||||
if ENABLED
|
|
||||||
DB_CONFIG = self.db_config = config(safe: true)['database']
|
|
||||||
DB = self.db_connect!
|
|
||||||
require_relative 'plugin/model' # if you have a model, include it now
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. create the database and tables
|
|
||||||
It can be done via 2 ways:
|
|
||||||
|
|
||||||
- migrations: **recommanded**.
|
|
||||||
This is safer and more reliable.
|
|
||||||
There is an example in the plugin [iamalive](plugins/iamalive/).
|
|
||||||
Checkout the documentation of the orm:
|
|
||||||
[sequel migrations](http://sequel.jeremyevans.net/rdoc/files/doc/migration_rdoc.html).
|
|
||||||
- manual: **NOT recommanded**.
|
|
||||||
Create the database and tables manually.
|
|
||||||
|
|
||||||
### 3. use it
|
|
||||||
|
|
||||||
You can access to the database via the constant ``DB``
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
class Plugin ...
|
|
||||||
...
|
|
||||||
def search_word m, word
|
|
||||||
found = DB[:words].where(word: word).first
|
|
||||||
m.reply found ? found[:id] : 'no such word'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. models
|
|
||||||
|
|
||||||
If you want to use models, don't forget to set the "dataset"
|
|
||||||
(association with the right database / table)
|
|
||||||
to avoid conflicts:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
class Model < Sequel::Model
|
|
||||||
set_dataset DB[:admins]
|
|
||||||
end
|
|
||||||
```
|
|
24
Gemfile
24
Gemfile
|
@ -1,29 +1,7 @@
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
#irc
|
gem 'net-ping'
|
||||||
gem 'cinch'
|
gem 'cinch'
|
||||||
|
|
||||||
# scrap yt
|
|
||||||
gem 'mechanize'
|
|
||||||
|
|
||||||
# debug
|
|
||||||
gem 'pry'
|
gem 'pry'
|
||||||
gem 'colorize'
|
gem 'colorize'
|
||||||
|
|
||||||
#network
|
|
||||||
gem 'net-ping'
|
|
||||||
|
|
||||||
#proxy
|
|
||||||
gem 'htauth'
|
gem 'htauth'
|
||||||
|
|
||||||
#iamalive
|
|
||||||
gem 'sequel'
|
|
||||||
# gem 'sqlite3'
|
|
||||||
gem 'pg'
|
|
||||||
|
|
||||||
#encrypt
|
|
||||||
gem 'tor257'
|
|
||||||
|
|
||||||
#other
|
|
||||||
gem 'nomorebeer'
|
|
||||||
gem 'i18n'
|
|
||||||
|
|
48
Gemfile.lock
48
Gemfile.lock
|
@ -1,47 +1,19 @@
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
cinch (2.2.7)
|
cinch (2.2.6)
|
||||||
coderay (1.1.0)
|
coderay (1.1.0)
|
||||||
colorize (0.7.7)
|
colorize (0.7.7)
|
||||||
domain_name (0.5.25)
|
highline (1.7.2)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
htauth (1.2.0)
|
||||||
htauth (2.0.0)
|
highline (~> 1.6)
|
||||||
http-cookie (1.0.2)
|
|
||||||
domain_name (~> 0.5)
|
|
||||||
i18n (0.7.0)
|
|
||||||
mechanize (2.7.3)
|
|
||||||
domain_name (~> 0.5, >= 0.5.1)
|
|
||||||
http-cookie (~> 1.0)
|
|
||||||
mime-types (~> 2.0)
|
|
||||||
net-http-digest_auth (~> 1.1, >= 1.1.1)
|
|
||||||
net-http-persistent (~> 2.5, >= 2.5.2)
|
|
||||||
nokogiri (~> 1.4)
|
|
||||||
ntlm-http (~> 0.1, >= 0.1.1)
|
|
||||||
webrobots (>= 0.0.9, < 0.2)
|
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
mime-types (2.6.2)
|
net-ping (1.7.7)
|
||||||
mini_portile (0.6.2)
|
pry (0.10.1)
|
||||||
net-http-digest_auth (1.4)
|
|
||||||
net-http-persistent (2.9.4)
|
|
||||||
net-ping (1.7.8)
|
|
||||||
nokogiri (1.6.6.2)
|
|
||||||
mini_portile (~> 0.6.0)
|
|
||||||
nomorebeer (1.1)
|
|
||||||
ntlm-http (0.1.1)
|
|
||||||
pg (0.18.3)
|
|
||||||
pry (0.10.3)
|
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
method_source (~> 0.8.1)
|
method_source (~> 0.8.1)
|
||||||
slop (~> 3.4)
|
slop (~> 3.4)
|
||||||
sequel (4.27.0)
|
|
||||||
slop (3.6.0)
|
slop (3.6.0)
|
||||||
tor257 (0.2)
|
|
||||||
nomorebeer (~> 1.1)
|
|
||||||
unf (0.1.4)
|
|
||||||
unf_ext
|
|
||||||
unf_ext (0.0.7.1)
|
|
||||||
webrobots (0.1.1)
|
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
@ -50,14 +22,8 @@ DEPENDENCIES
|
||||||
cinch
|
cinch
|
||||||
colorize
|
colorize
|
||||||
htauth
|
htauth
|
||||||
i18n
|
|
||||||
mechanize
|
|
||||||
net-ping
|
net-ping
|
||||||
nomorebeer
|
|
||||||
pg
|
|
||||||
pry
|
pry
|
||||||
sequel
|
|
||||||
tor257
|
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.11.2
|
1.10.5
|
||||||
|
|
122
README.md
122
README.md
|
@ -1,30 +1,21 @@
|
||||||
# botpop
|
# botpop
|
||||||
[![Code Climate](https://codeclimate.com/github/Nephos/botpop/badges/gpa.svg)](https://codeclimate.com/github/Nephos/botpop)
|
[![Code Climate](https://codeclimate.com/github/pouleta/botpop/badges/gpa.svg)](https://codeclimate.com/github/pouleta/botpop)
|
||||||
[![GitHub version](https://badge.fury.io/gh/Nephos%2Fbotpop.svg)](http://badge.fury.io/gh/Nephos%2Fbotpop)
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
- Ruby 2.0 or greater
|
|
||||||
- Postgresql 9.3 or greater
|
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
## Installation
|
|
||||||
Ruby 2 or greater is required. To be compatible with Ruby 1.9, you can try :
|
Ruby 2 or greater is required. To be compatible with Ruby 1.9, you can try :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sed 's/prepend/include/g' -i botpop.rb
|
sed 's/prepend/include/g' -i botpop.rb
|
||||||
```
|
```
|
||||||
but i did never try... You better update ruby ! ;)
|
but i did never try... You better update ruby ! ;)
|
||||||
|
|
||||||
Too install the stuff, just do :
|
|
||||||
```bash
|
```bash
|
||||||
bundle install # install the required gems
|
bundle install
|
||||||
cp modules_config.yml.example modules_config.yml
|
|
||||||
editor modules_config.yml # set the database settings, etc.
|
|
||||||
# create your database
|
|
||||||
rake db:install # migrate the base plugin
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
to install the gems.
|
||||||
|
|
||||||
|
|
||||||
## Arguments
|
## Arguments
|
||||||
By default, only the first occurence of the argument will be used, unless specified.
|
By default, only the first occurence of the argument will be used, unless specified.
|
||||||
|
@ -60,19 +51,12 @@ end
|
||||||
Some official plugins are developped. You can propose your own creation by pull request, or add snippets link to the wiki.
|
Some official plugins are developped. You can propose your own creation by pull request, or add snippets link to the wiki.
|
||||||
|
|
||||||
## List
|
## List
|
||||||
- [Base](https://github.com/Nephos/botpop/blob/master/plugins/base.rb) : this is a basic plugin, providing __version, code, help, and troll__. It also provide a full groups's system.
|
- [Base](https://github.com/pouleta/botpop/blob/master/plugins/base.rb) : this is a basic plugin, providing __version, code, help, and troll__
|
||||||
- [Network](https://github.com/Nephos/botpop/blob/master/plugins/network.rb) : an usefull plugin with commands __ping, ping ip, ping http, traceroute, dos attack and poke__
|
- [Network](https://github.com/pouleta/botpop/blob/master/plugins/network.rb) : an usefull plugin with commands __ping, ping ip, ping http, traceroute, dos attack and poke__
|
||||||
- [Searchable](https://github.com/Nephos/botpop/blob/master/plugins/searchable.rb) : a little plugin providing irc research with engines like __google, wikipedia, ruby-doc, etc...__
|
- [Searchable](https://github.com/pouleta/botpop/blob/master/plugins/searchable.rb) : a little plugin providing irc research with engines like __google, wikipedia, ruby-doc, etc...__
|
||||||
- [Proxy](https://github.com/Nephos/botpop/blob/master/plugins/proxy.rb) : an audacious plugin to create user access to a local proxy
|
- [Coupon](https://github.com/pouleta/botpop/blob/master/plugins/coupons.rb) : the original aim of the bot. It get coupons for the challenge __pathwar__
|
||||||
- [Log](https://github.com/Nephos/botpop/blob/master/plugins/log.rb) : simple logger
|
- [Intranet](https://github.com/pouleta/botpop/blob/master/plugins/intranet.rb) : an useless plugin to check the intranet of epitech
|
||||||
- [IAmAlive](https://github.com/Nephos/botpop/tree/master/plugins/iamalive) : a plugin to learn how to respond to the users. Fucking machine learning, oh yearh.
|
- [Proxy](https://github.com/pouleta/botpop/blob/master/plugins/proxy.rb) : an audacious plugin to create user access to a local proxy
|
||||||
- [CeQueTuDisNaAucunSens](https://github.com/Nephos/botpop/tree/master/plugins/cequetudisnaaucunsens.rb) : a funny plugin to say "ce que tu dis n'a aucun sens" without any meaning.
|
|
||||||
- [Points](https://github.com/Nephos/botpop/tree/master/plugins/points.rb) : a gem to add points to an user. ``!p noob for_you``
|
|
||||||
- [Anecdote](https://github.com/Nephos/botpop/blob/master/plugins/anecdote.rb) : a cool meme generator plugin with nazi and youtuber. French meme.
|
|
||||||
|
|
||||||
### In version 0.X, not upgraded to v1
|
|
||||||
- [Coupon](https://github.com/Nephos/botpop/blob/master/plugins/coupons.rb) : the original aim of the bot. It get coupons for the challenge __pathwar__
|
|
||||||
- [Intranet](https://github.com/Nephos/botpop/blob/master/plugins/intranet.rb) : an useless plugin to check the intranet of epitech
|
|
||||||
|
|
||||||
|
|
||||||
## Create your own
|
## Create your own
|
||||||
|
@ -83,17 +67,17 @@ You should take the time to read the documentation before developping anything.
|
||||||
|
|
||||||
|
|
||||||
### Example of new plugin
|
### Example of new plugin
|
||||||
A full example of plugin code is provided in the commented file : [Example of Fury Plugin](https://github.com/Nephos/botpop/blob/master/plugins/example.rb)
|
A full example of plugin code is provided in the commented file : [Example of Fury Plugin](https://github.com/pouleta/botpop/blob/master/plugins/example.rb)
|
||||||
|
|
||||||
First, put your ruby code file in ``plugins/``, and put your code in the scope :
|
First, put your ruby code file in ``plugins/``, and put your code in the scope :
|
||||||
```ruby
|
```ruby
|
||||||
class MyFuryPlugin < Botpop::Plugin
|
module BotpopPlugins
|
||||||
include Cinch::Plugin
|
module MyFuryPlugin
|
||||||
|
def self.exec_whatkingofanimal m
|
||||||
def exec_whatkingofanimal m
|
m.reply "Die you son of a" + ["lion", "pig", "red panda"].shuffle.first + " !!"
|
||||||
m.reply "Die you son of a" + ["lion", "pig", "red panda"].sample + " !!"
|
end
|
||||||
|
...code...
|
||||||
end
|
end
|
||||||
...code...
|
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -101,76 +85,46 @@ end
|
||||||
### Matching messages
|
### Matching messages
|
||||||
To create a matching to respond to a message, you have to specifie in your plugin :
|
To create a matching to respond to a message, you have to specifie in your plugin :
|
||||||
```ruby
|
```ruby
|
||||||
class MyFuryPlugin < Botpop::Plugin
|
module BotpopPlugins
|
||||||
include Cinch::Plugin
|
module MyFuryPlugin
|
||||||
match(/!whatkingofanimal.*/, use_prefix: false, method: :exec_whatkingofanimal)
|
MATCH = lambda do |parent, plugin|
|
||||||
...code...
|
parent.on :message, /!whatkingofanimal.*/ do |m| plugin.exec_whatkingofanimal m end
|
||||||
|
end
|
||||||
|
...code...
|
||||||
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Add entry to the !help command
|
### Add entry to the !help command
|
||||||
The __official plugin__ [Base](https://github.com/Nephos/botpop/blob/master/plugins/base.rb) provides the command __!help__ and __!help plugin__.
|
The __official plugin__ [Base](https://github.com/pouleta/botpop/blob/master/plugins/base.rb) provides the command __!help__ and __!help plugin__.
|
||||||
|
|
||||||
It list the avaliable commands of the plugins. You can add your help to your plugin by providing a __HELP__ constant.
|
It list the avaliable commands of the plugins. You can add your help to your plugin by providing a __HELP__ constant.
|
||||||
__The strings should be as short as possible.__
|
__The strings should be as short as possible.__
|
||||||
You should write it like the following:
|
You should write it like the following:
|
||||||
```ruby
|
```ruby
|
||||||
class MyFuryPlugin < Botpop::Plugin
|
module BotpopPlugins
|
||||||
HELP = ["!whatkingofanimal", "!animallist", "!checkanimal [type]"]
|
module MyFuryPlugin
|
||||||
...code...
|
HELP = ["!whatkingofanimal", "!animallist", "!checkanimal [type]"]
|
||||||
|
...code...
|
||||||
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Enable and disable plugin
|
### Enable and disable plugin
|
||||||
You can enable or disable plugin by using the constant __ENABLED__.
|
You can enable or disable plugin by using the constant __ENABLED__.
|
||||||
|
It should be linked with the __Botpop::CONFIG__.
|
||||||
The constant must be defined by the developper of the plugin.
|
The constant must be defined by the developper of the plugin.
|
||||||
For example, you can implement it like :
|
For example, you can implement it like :
|
||||||
```ruby
|
```ruby
|
||||||
class MyFuryPlugin < Botpop::Plugin
|
module BotpopPlugins
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
module MyFuryPlugin
|
||||||
|
CONFIG = Botpop::CONFIG['myfurry'] || raise(MissingConfigurationZone, 'myfurry')
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, a simple line in the ``modules_configuration.yml`` file should be enough.
|
Then, a simple line in the ``modules_configuration.yml`` file should be enough.
|
||||||
|
|
||||||
|
|
||||||
### Plugin Configuration
|
|
||||||
You can configure your plugins via the file ``modules_configuration.yml``.
|
|
||||||
If you considere that your plugin needs a particular configuration file, then create a new one il the ``plugins`` directory.
|
|
||||||
|
|
||||||
To use the configuration loaded by ``modules_configuration.yml``, use the method ``config``.
|
|
||||||
|
|
||||||
``config`` takes an optionnal Hash as argument. It can take:
|
|
||||||
|
|
||||||
- ``:safe => (true or false)``
|
|
||||||
- ``:name => (string or symbol)``
|
|
||||||
|
|
||||||
This method returns a Hash with configuration.
|
|
||||||
|
|
||||||
By default, the method raise a ``MissingConfigurationZone`` error if no entry in the ``modules_configuration.yml`` file.
|
|
||||||
|
|
||||||
The configuration file ``modules_configuration.yml`` must seems like :
|
|
||||||
```yaml
|
|
||||||
name:
|
|
||||||
entry: "string"
|
|
||||||
entry2:
|
|
||||||
- 1
|
|
||||||
- 2.2
|
|
||||||
- "ohoh"
|
|
||||||
- nextelement:
|
|
||||||
- oh oh !
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, the ``modules_configuration.yml`` file is configured for default plugins.
|
|
||||||
|
|
||||||
### Plugin Database
|
|
||||||
|
|
||||||
Check this specified [README FOR DATABASE IN PLUGINS](DATABASE_EXTENSION.md)
|
|
||||||
|
|
||||||
### Rights managements (users, groups)
|
|
||||||
|
|
||||||
Requires postgresql, because it uses the pg_array extension.
|
|
||||||
|
|
||||||
Check this specified [README FOR RIGHTS MANAGEMENT](RIGHTS_MANAGEMENT.md)
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
# How to use rights ?
|
|
||||||
|
|
||||||
In your plugin, add the method ``cmd_allowed?`` and use it like in the following example:
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
class Plugin < Botpop::Plugin
|
|
||||||
...
|
|
||||||
def cmd_allowed? m
|
|
||||||
return if not Base.cmd_allowed? m, ["groupname"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_some_match m
|
|
||||||
return Base.cmd_allowed? m, ["iaa"]
|
|
||||||
end
|
|
||||||
```
|
|
16
Rakefile
16
Rakefile
|
@ -1,17 +1,7 @@
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
require 'yaml'
|
task :default => [:test]
|
||||||
CONFIG = YAML.load_file("modules_config.yml")
|
|
||||||
|
|
||||||
#require 'sequel'
|
task :test do
|
||||||
#DB_BASE = Sequel.connect(CONFIG['base']['database'])
|
ruby "test/test.rb"
|
||||||
|
|
||||||
#task :default => ["x:x"]
|
|
||||||
|
|
||||||
namespace :db do
|
|
||||||
task :install do
|
|
||||||
# TODO: use CONFIG['base']
|
|
||||||
`sequel -m plugins/base/migrations postgres://root:toor@localhost:5432/botpop_base`
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
16
arguments.rb
16
arguments.rb
|
@ -1,8 +1,8 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
class Arguments
|
class Arguments
|
||||||
|
|
||||||
# @param name [String] the option to search
|
# @arg : name [String] the option to search
|
||||||
# @param name [Array] the options to search (multiples keys avaliables)
|
# @arg : name [Array] the options to search (multiples keys avaliables)
|
||||||
def get_one_argument(name, default_value)
|
def get_one_argument(name, default_value)
|
||||||
if name.is_a? String
|
if name.is_a? String
|
||||||
i = @argv.index(name)
|
i = @argv.index(name)
|
||||||
|
@ -83,13 +83,17 @@ class Arguments
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_plugins
|
def disable_plugins
|
||||||
|
i = 0
|
||||||
plugins = []
|
plugins = []
|
||||||
argv = @argv.dup
|
argv = @argv.dup
|
||||||
loop do
|
while i
|
||||||
i = argv.index('--plugin-disable')
|
i = argv.index('--plugin-disable')
|
||||||
break unless i
|
if i
|
||||||
plugins << @argv[i + 1]
|
plugin = argv[i + 1]
|
||||||
argv = argv[(i+2)..(-1)]
|
plugin = plugin + '.rb' if plugin[-4..-1] != '.rb'
|
||||||
|
plugins << File.expand_path(plugin, plugin_directory)
|
||||||
|
argv = argv[(i+2)..(-1)]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return plugins
|
return plugins
|
||||||
end
|
end
|
||||||
|
|
82
botpop.rb
82
botpop.rb
|
@ -13,54 +13,42 @@ require 'yaml'
|
||||||
require 'colorize'
|
require 'colorize'
|
||||||
|
|
||||||
require_relative 'arguments'
|
require_relative 'arguments'
|
||||||
require_relative 'botpop_plugin_inclusion'
|
require_relative 'builtin'
|
||||||
require_relative 'builtins'
|
|
||||||
require_relative 'database'
|
require_relative "botpop_plugin_inclusion"
|
||||||
|
|
||||||
|
$botpod_arguments ||= ARGV
|
||||||
|
|
||||||
class Botpop
|
class Botpop
|
||||||
|
|
||||||
class Plugin
|
|
||||||
def self.config(infos={})
|
|
||||||
name = (infos[:name] || self.to_s.downcase).to_s
|
|
||||||
config = Botpop::CONFIG[name]
|
|
||||||
return config || (raise(MissingConfigurationZone, self.to_s) unless infos[:safe])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.load_version
|
|
||||||
begin
|
|
||||||
return IO.read('version')
|
|
||||||
rescue Errno::ENOENT
|
|
||||||
puts "No version specified".red
|
|
||||||
return "???"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.include_plugins
|
|
||||||
PluginInclusion.plugins_include! ARGUMENTS
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.load_plugins
|
|
||||||
Module.constants.select{ |m|
|
|
||||||
(m = Module.const_get(m) rescue false) and
|
|
||||||
(m.is_a?(Class)) and
|
|
||||||
(m.ancestors.include?(Plugin)) and
|
|
||||||
(m.included_modules.include?(Cinch::Plugin))
|
|
||||||
}.
|
|
||||||
select{|m| not ARGUMENTS.disable_plugins.include? m.to_s
|
|
||||||
}.
|
|
||||||
map{|m| Module.const_get(m)
|
|
||||||
}.
|
|
||||||
select{|m| m::ENABLED}
|
|
||||||
end
|
|
||||||
|
|
||||||
# FIRST LOAD THE CONFIGURATION
|
# FIRST LOAD THE CONFIGURATION
|
||||||
ARGUMENTS = Arguments.new(ARGV)
|
ARGUMENTS = Arguments.new($botpod_arguments)
|
||||||
VERSION = load_version()
|
VERSION = IO.read('version')
|
||||||
CONFIG = YAML.load_file(ARGUMENTS.config_file)
|
CONFIG = YAML.load_file(ARGUMENTS.config_file)
|
||||||
TARGET = /[[:alnum:]_\-\.]+/
|
TARGET = /[[:alnum:]_\-\.]+/
|
||||||
include_plugins()
|
|
||||||
PLUGINS = load_plugins()
|
PluginInclusion::plugins_include! ARGUMENTS
|
||||||
|
|
||||||
|
# THEN LOAD / NOT THE PLUGINS
|
||||||
|
def self.plugins_load!
|
||||||
|
@@plugins = []
|
||||||
|
BotpopPlugins.constants.each do |const|
|
||||||
|
plugin = BotpopPlugins.const_get(const)
|
||||||
|
next if not plugin.is_a? Module
|
||||||
|
if plugin::ENABLED == false
|
||||||
|
puts "Disabled plugin #{plugin}".yellow if $botpop_include_verbose != false
|
||||||
|
next
|
||||||
|
end rescue nil
|
||||||
|
puts "Load plugin #{plugin}".green if $botpop_include_verbose != false
|
||||||
|
# prepend plugin
|
||||||
|
@@plugins << plugin
|
||||||
|
end
|
||||||
|
end
|
||||||
|
plugins_load!
|
||||||
|
|
||||||
|
def self.plugins
|
||||||
|
@@plugins.dup
|
||||||
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
@engine.start
|
@engine.start
|
||||||
|
@ -75,7 +63,10 @@ class Botpop
|
||||||
c.port = ARGUMENTS.port
|
c.port = ARGUMENTS.port
|
||||||
c.user = ARGUMENTS.user
|
c.user = ARGUMENTS.user
|
||||||
c.nick = ARGUMENTS.nick
|
c.nick = ARGUMENTS.nick
|
||||||
c.plugins.plugins = PLUGINS
|
end
|
||||||
|
@@plugins.each do |plugin|
|
||||||
|
puts "Load matchings of the plugin #{plugin}".green
|
||||||
|
plugin::MATCH.call(self, plugin) rescue puts "No matching found for #{plugin}".red
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -84,10 +75,5 @@ end
|
||||||
|
|
||||||
if __FILE__ == $0
|
if __FILE__ == $0
|
||||||
$bot = Botpop.new
|
$bot = Botpop.new
|
||||||
trap("SIGINT") do
|
|
||||||
puts "\b"
|
|
||||||
puts "SIGINT Catched"
|
|
||||||
exit
|
|
||||||
end
|
|
||||||
$bot.start
|
$bot.start
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,35 +1,39 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
module PluginInclusion
|
class Botpop
|
||||||
def self.plugin_error_failure! e, f
|
|
||||||
STDERR.puts "Error during loading the file #{f}".red
|
|
||||||
STDERR.puts "#{e.class}: #{e.message}".red.bold
|
|
||||||
STDERR.puts "---- Trace ----"
|
|
||||||
STDERR.puts e.backtrace.join("\n").black.bold
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.plugin_include! f
|
module PluginInclusion
|
||||||
return false if File.basename(f) == "example.rb"
|
|
||||||
begin
|
def self.plugin_error_failure! e, f
|
||||||
if $botpop_include_verbose != false
|
STDERR.puts "Error during loading the file #{f}".red
|
||||||
puts "Loading plugin file ... " + f.green + " ... " + require_relative(f).to_s
|
STDERR.puts "#{e.class}: #{e.message}".red.bold
|
||||||
else
|
STDERR.puts "---- Trace ----"
|
||||||
require_relative(f)
|
STDERR.puts e.backtrace.join("\n").black.bold
|
||||||
end
|
exit 1
|
||||||
rescue => e
|
|
||||||
plugin_error_failure! e, f
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# THEN INCLUDE THE PLUGINS (STATE MAY BE DEFINED BY THE PREVIOUS CONFIG)
|
def self.plugin_include! f
|
||||||
def self.plugins_include! arguments
|
begin
|
||||||
Dir[File.expand_path '*.rb', arguments.plugin_directory].each do |f|
|
if $botpop_include_verbose != false
|
||||||
if !arguments.disable_plugins.include? f
|
puts "Loading plugin file ... " + f.green + " ... " + require_relative(f).to_s
|
||||||
plugin_include! f
|
else
|
||||||
|
require_relative(f)
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
plugin_error_failure! e, f
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# THEN INCLUDE THE PLUGINS (STATE MAY BE DEFINED BY THE PREVIOUS CONFIG)
|
||||||
|
def self.plugins_include! arguments
|
||||||
|
Dir[File.expand_path '*.rb', arguments.plugin_directory].each do |f|
|
||||||
|
if !arguments.disable_plugins.include? f
|
||||||
|
plugin_include! f
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
45
builtin.rb
Normal file
45
builtin.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
module BotpopBuiltins
|
||||||
|
|
||||||
|
def self.dos(ip, duration)
|
||||||
|
`timeout #{duration} hping --flood '#{ip}' 2>&1`
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.ping(ip)
|
||||||
|
Net::Ping::External.new(ip).ping?
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.intra_state
|
||||||
|
Net::Ping::External.new("intra.epitech.eu").ping? ? "Intra ok" : "Intra down"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.trace ip
|
||||||
|
`tracepath '#{ip}'`.to_s.split("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_msg m
|
||||||
|
URI.encode(m.params[1..-1].join(' ').gsub(/\![^ ]+ /, ''))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_ip m
|
||||||
|
m.params[1..-1].join(' ').gsub(/\![^ ]+ /, '').gsub(/[^[:alnum:]\-\_\.]/, '')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_ip_from_nick m
|
||||||
|
nick = get_ip m
|
||||||
|
ip = m.target.users.keys.find{|u| u.nick == nick rescue nil}.host rescue nil
|
||||||
|
return {nick: nick, ip: ip}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module BotpopPlugins
|
||||||
|
prepend BotpopBuiltins
|
||||||
|
end
|
||||||
|
|
||||||
|
class MissingConfigurationZone < RuntimeError
|
||||||
|
end
|
||||||
|
|
||||||
|
class MissingConfigurationEntry < RuntimeError
|
||||||
|
end
|
43
builtins.rb
43
builtins.rb
|
@ -1,43 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
class Botpop
|
|
||||||
module Builtins
|
|
||||||
|
|
||||||
def self.dos(ip, duration)
|
|
||||||
`timeout #{duration} hping --flood '#{ip}' 2>&1`
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.ping(ip)
|
|
||||||
Net::Ping::External.new(ip).ping?
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.intra_state
|
|
||||||
Net::Ping::External.new("intra.epitech.eu").ping? ? "Intra ok" : "Intra down"
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.trace ip
|
|
||||||
`tracepath '#{ip}'`.to_s.split("\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.get_msg m
|
|
||||||
URI.encode(m.params[1..-1].join(' ').gsub(/\![^ ]+ /, ''))
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.get_ip m
|
|
||||||
m.params[1..-1].join(' ').gsub(/\![^ ]+ /, '').gsub(/[^[:alnum:]\-\_\.]/, '')
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.get_ip_from_nick m
|
|
||||||
nick = get_ip m
|
|
||||||
ip = m.target.users.keys.find{|u| u.nick == nick rescue nil}.host rescue nil
|
|
||||||
return {nick: nick, ip: ip}
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class MissingConfigurationZone < RuntimeError
|
|
||||||
end
|
|
||||||
|
|
||||||
class MissingConfigurationEntry < RuntimeError
|
|
||||||
end
|
|
|
@ -3,5 +3,3 @@ moul -- guest
|
||||||
ernestjkaufman -- guest
|
ernestjkaufman -- guest
|
||||||
FolenScare -- guest
|
FolenScare -- guest
|
||||||
JoycePF -- guest
|
JoycePF -- guest
|
||||||
Deborah -- guest
|
|
||||||
Shigugu -- guest
|
|
||||||
|
|
21
database.rb
21
database.rb
|
@ -1,21 +0,0 @@
|
||||||
#coding: utf-8
|
|
||||||
|
|
||||||
class Botpop
|
|
||||||
class Plugin
|
|
||||||
module Database
|
|
||||||
|
|
||||||
def self.append_features(b)
|
|
||||||
b.extend self
|
|
||||||
end
|
|
||||||
|
|
||||||
attr_accessor :db_config
|
|
||||||
attr_reader :db
|
|
||||||
def db_connect!
|
|
||||||
require 'sequel'
|
|
||||||
@db = Sequel.connect(@db_config)
|
|
||||||
@db
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,67 +1,5 @@
|
||||||
base:
|
|
||||||
enable: true
|
|
||||||
help_wait_duration: 120
|
|
||||||
database:
|
|
||||||
adapter: postgres
|
|
||||||
host: localhost
|
|
||||||
port: 5432
|
|
||||||
user: root
|
|
||||||
password: toor
|
|
||||||
database: botpop_base
|
|
||||||
|
|
||||||
dice:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
eip:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
rootme:
|
|
||||||
enable: false
|
|
||||||
|
|
||||||
points:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
anecdote:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
log:
|
|
||||||
enable: true
|
|
||||||
default_started: false
|
|
||||||
|
|
||||||
encrypt:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
puppet:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
taggle:
|
|
||||||
enable: true
|
|
||||||
ntimes: 10
|
|
||||||
wait: 0.3
|
|
||||||
|
|
||||||
youtube:
|
|
||||||
enable: true
|
|
||||||
display: "Youtube: ___TITLE___ ___URL___"
|
|
||||||
reduce_url: https://youtu.be/___ID___
|
|
||||||
search_url: https://www.youtube.com/results?search_query=___MSG___
|
|
||||||
|
|
||||||
poilo:
|
|
||||||
enable: false
|
|
||||||
list:
|
|
||||||
u: cul
|
|
||||||
a: bras
|
|
||||||
o: dos
|
|
||||||
i: kiki
|
|
||||||
eu: lepreux
|
|
||||||
y: nazi
|
|
||||||
oi: petit-pois
|
|
||||||
eau: bébé oiseau
|
|
||||||
au: marmot
|
|
||||||
ou: doudou
|
|
||||||
an: manant
|
|
||||||
|
|
||||||
searchable:
|
searchable:
|
||||||
#yt: https://www.youtube.com/results?search_query=___MSG___ # use the plugin youtube instead
|
yt: https://www.youtube.com/results?search_query=___MSG___
|
||||||
xv: http://www.xvideos.com/?k=___MSG___
|
xv: http://www.xvideos.com/?k=___MSG___
|
||||||
yp: https://www.youporn.com/search/?query=___MSG___
|
yp: https://www.youporn.com/search/?query=___MSG___
|
||||||
|
|
||||||
|
@ -99,6 +37,17 @@ searchable:
|
||||||
pkmn: http://pokemondb.net/search?q=___MSG___
|
pkmn: http://pokemondb.net/search?q=___MSG___
|
||||||
tek: https://intra.epitech.eu/user/___MSG___
|
tek: https://intra.epitech.eu/user/___MSG___
|
||||||
|
|
||||||
|
base:
|
||||||
|
enable: true
|
||||||
|
help_wait_duration: 120
|
||||||
|
|
||||||
|
logger:
|
||||||
|
enable: true
|
||||||
|
file: logger.log
|
||||||
|
|
||||||
|
intranet:
|
||||||
|
enable: true
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable: true
|
enable: true
|
||||||
dos_wait: 10s
|
dos_wait: 10s
|
||||||
|
@ -106,6 +55,10 @@ network:
|
||||||
trace_duration_init: 0.3s
|
trace_duration_init: 0.3s
|
||||||
trace_duration_incr: 0.1s
|
trace_duration_incr: 0.1s
|
||||||
|
|
||||||
|
coupons:
|
||||||
|
enable: false
|
||||||
|
display_coupons: true
|
||||||
|
|
||||||
proxy:
|
proxy:
|
||||||
enable: false
|
enable: false
|
||||||
ip_addr: localhost
|
ip_addr: localhost
|
||||||
|
@ -117,20 +70,10 @@ epitech:
|
||||||
enable: false
|
enable: false
|
||||||
|
|
||||||
iamalive:
|
iamalive:
|
||||||
enable: true
|
enable: false
|
||||||
default_mode: live
|
database_file: plugins/iamalive.database.yaml
|
||||||
database:
|
|
||||||
adapter: postgres
|
|
||||||
host: localhost
|
|
||||||
port: 5432
|
|
||||||
user: root
|
|
||||||
password: toor
|
|
||||||
database: botpop_iamalive
|
|
||||||
|
|
||||||
cequetudisnaaucunsens:
|
say_goodbye:
|
||||||
enabled: true
|
|
||||||
|
|
||||||
saygoodbye:
|
|
||||||
chapui_s:
|
chapui_s:
|
||||||
- "@chapui_s t'es là ?"
|
- "@chapui_s t'es là ?"
|
||||||
- "chapui_s !!! T'es où ?"
|
- "chapui_s !!! T'es où ?"
|
||||||
|
@ -159,3 +102,6 @@ saygoodbye:
|
||||||
- "No râge de mon gradÂge !"
|
- "No râge de mon gradÂge !"
|
||||||
poulet_a:
|
poulet_a:
|
||||||
- "Nan mais c'est un scandale ! Pourquoi j'ai grade A ?"
|
- "Nan mais c'est un scandale ! Pourquoi j'ai grade A ?"
|
||||||
|
|
||||||
|
example:
|
||||||
|
enable: false
|
2
plugins/.gitignore
vendored
Normal file
2
plugins/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
coupon_login.yml
|
||||||
|
iamalive.database.yaml
|
|
@ -1,46 +0,0 @@
|
||||||
require 'nokogiri'
|
|
||||||
require 'net/http'
|
|
||||||
|
|
||||||
class Anecdote < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/!a(necdote)? (.+)/, use_prefix: false, method: :exec_new)
|
|
||||||
|
|
||||||
HELP = ["!anecdote <...>"]
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def exec_new m, _, s
|
|
||||||
s.downcase!
|
|
||||||
f = I18n.transliterate(s)[0]
|
|
||||||
x = "Après je vous propose "
|
|
||||||
x += (%w(a e i o u y).include?(f) ? "d'" : "de ") if not s.match(/^(d'|de ).+/)
|
|
||||||
s = x + s
|
|
||||||
url = URI.parse 'http://memegenerator.net/create/instance'
|
|
||||||
post_data = {
|
|
||||||
'imageID' => 14185932,
|
|
||||||
'generatorID' => 5374051,
|
|
||||||
'watermark1' => 1,
|
|
||||||
'uploadtoImgur' => 'true',
|
|
||||||
'text0' => s,
|
|
||||||
'text1' => "Ca fera une petite anecdote !!",
|
|
||||||
}
|
|
||||||
meme = nil
|
|
||||||
begin
|
|
||||||
Net::HTTP.start url.host do |http|
|
|
||||||
post = Net::HTTP::Post.new url.path
|
|
||||||
post.set_form_data post_data
|
|
||||||
res = http.request post
|
|
||||||
location = res['Location']
|
|
||||||
redirect = url + location
|
|
||||||
get = Net::HTTP::Get.new redirect.request_uri
|
|
||||||
res = http.request get
|
|
||||||
doc = Nokogiri.HTML res.body
|
|
||||||
meme = doc.css("meta")[7]['content']
|
|
||||||
end
|
|
||||||
rescue => _err
|
|
||||||
end
|
|
||||||
m.reply meme ? meme : "Achtung ! ACHTUUUUNG !!!"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
143
plugins/base.rb
143
plugins/base.rb
|
@ -1,85 +1,76 @@
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
require "i18n"
|
module BotpopPlugins
|
||||||
I18n.config.available_locales = [:en, :fr]
|
module Base
|
||||||
|
|
||||||
class Base < Botpop::Plugin
|
MATCH = lambda do |parent, plugin|
|
||||||
include Cinch::Plugin
|
parent.on :message, /!troll .+/ do |m| plugin.exec_troll m end
|
||||||
include Botpop::Plugin::Database
|
parent.on :message, "!version" do |m| plugin.exec_version m end
|
||||||
|
parent.on :message, "!code" do |m| plugin.exec_code m end
|
||||||
match(/^!troll .+/ , use_prefix: false, method: :exec_troll)
|
parent.on :message, "!cmds" do |m| plugin.exec_help m end
|
||||||
match "!version" , use_prefix: false, method: :exec_version
|
parent.on :message, "!help" do |m| plugin.exec_help m end
|
||||||
match "!code" , use_prefix: false, method: :exec_code
|
parent.on :message, /!help \w+/ do |m| plugin.exec_help_plugin m end
|
||||||
match "!cmds" , use_prefix: false, method: :exec_help
|
|
||||||
match "!help" , use_prefix: false, method: :exec_help
|
|
||||||
match(/^!help \w+/ , use_prefix: false, method: :exec_help_plugin)
|
|
||||||
|
|
||||||
match("!register", use_prefix: false, method: :user_register)
|
|
||||||
match("!user ls", use_prefix: false, method: :user_ls)
|
|
||||||
match(/^!user (\w+) group ls$/, use_prefix: false, method: :user_group_ls)
|
|
||||||
match(/^!user (\w+) group add (\w+)/, use_prefix: false, method: :user_group_add)
|
|
||||||
match(/^!user (\w+) group rm (\w+)/, use_prefix: false, method: :user_group_rm)
|
|
||||||
|
|
||||||
HELP = ["!troll [msg]", "!version", "!code", "!help [plugin]", "!cmds",
|
|
||||||
"!user ls", "!user <name> group <ls|add|rm> [group]"]
|
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
if ENABLED
|
|
||||||
DB_CONFIG = self.db_config = CONFIG['database']
|
|
||||||
DB = self.db_connect!
|
|
||||||
DB.extension :pg_array
|
|
||||||
require_relative 'base/UserModel'
|
|
||||||
require_relative 'base/user'
|
|
||||||
end
|
|
||||||
|
|
||||||
def help_wait_before_quit
|
|
||||||
HELP_WAIT_DURATION.times do
|
|
||||||
sleep 1
|
|
||||||
@@help_time += 1
|
|
||||||
end
|
end
|
||||||
end
|
HELP = ["!troll [msg]", "!version", "!code", "!help [plugin]", "!cmds"]
|
||||||
|
CONFIG = Botpop::CONFIG['base'] || raise(MissingConfigurationZone, 'base')
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
|
|
||||||
def help_get_plugins_str
|
def self.help_wait_before_quit
|
||||||
["Plugins found : " + Botpop::PLUGINS.size.to_s] +
|
HELP_WAIT_DURATION.times do
|
||||||
Botpop::PLUGINS.map do |plugin|
|
sleep 1
|
||||||
plugin.to_s.split(':').last
|
@help_time += 1
|
||||||
end.compact
|
end
|
||||||
end
|
|
||||||
|
|
||||||
HELP_WAIT_DURATION = config['help_wait_duration'] || 120
|
|
||||||
def help m
|
|
||||||
m.reply help_get_plugins_str.join(', ')
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_version m
|
|
||||||
m.reply Botpop::VERSION
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_code m
|
|
||||||
m.reply "https://github.com/Nephos/botpop"
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_help m
|
|
||||||
help m
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_help_plugin m
|
|
||||||
module_name = m.message.split(" ").last.downcase
|
|
||||||
i = Botpop::PLUGINS.map{|e| e.to_s.split(":").last.downcase}.index(module_name)
|
|
||||||
if i.nil?
|
|
||||||
m.reply "No plugin #{module_name}"
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
plugin = Botpop::PLUGINS[i]
|
|
||||||
m.reply plugin::HELP.join(', ')
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_troll m
|
def self.help_get_plugins_str
|
||||||
# hours = (Time.now.to_i - Time.gm(2015, 04, 27, 9).to_i) / 60 / 60
|
["Plugins found : " + Botpop.plugins.size.to_s] +
|
||||||
s = Botpop::Builtins.get_msg m
|
Botpop.plugins.map do |plugin|
|
||||||
url = "http://www.fuck-you-internet.com/delivery.php?text=#{s}"
|
plugin.to_s.split(':').last + ': ' + plugin::HELP.join(', ') rescue nil
|
||||||
m.reply url
|
end.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
|
HELP_WAIT_DURATION = CONFIG['help_wait_duration'] || 120
|
||||||
|
def self.help m
|
||||||
|
@help_lock ||= Mutex.new
|
||||||
|
if @help_lock.try_lock
|
||||||
|
@help_time = 0
|
||||||
|
help_get_plugins_str().each{|str| m.reply str} # display
|
||||||
|
help_wait_before_quit rescue nil
|
||||||
|
@help_lock.unlock
|
||||||
|
else
|
||||||
|
m.reply "Help already sent #{@help_time} seconds ago. Wait #{HELP_WAIT_DURATION - @help_time} seconds more."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_version m
|
||||||
|
m.reply Botpop::VERSION
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_code m
|
||||||
|
m.reply "https://github.com/pouleta/botpop"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_help m
|
||||||
|
help m
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_help_plugin m
|
||||||
|
module_name = m.message.split(" ").last
|
||||||
|
i = Botpop.plugins.map{|e| e.to_s.split(":").last}.index(module_name)
|
||||||
|
if i.nil?
|
||||||
|
m.reply "No plugin #{module_name}"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
plugin = Botpop.plugins[i]
|
||||||
|
m.reply plugin::HELP.join(', ')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_troll m
|
||||||
|
# hours = (Time.now.to_i - Time.gm(2015, 04, 27, 9).to_i) / 60 / 60
|
||||||
|
s = BotpopBuiltins.get_msg m
|
||||||
|
url = "http://www.fuck-you-internet.com/delivery.php?text=#{s}"
|
||||||
|
m.reply url
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
require 'sequel'
|
|
||||||
|
|
||||||
class User < Sequel::Model
|
|
||||||
|
|
||||||
def is_admin?
|
|
||||||
self.admin
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_group
|
|
||||||
end
|
|
||||||
|
|
||||||
def del_group
|
|
||||||
end
|
|
||||||
|
|
||||||
def belongs_to? group
|
|
||||||
self.groups.include? group
|
|
||||||
end
|
|
||||||
|
|
||||||
set_dataset Base::DB[:users]
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,10 +0,0 @@
|
||||||
Sequel.migration do
|
|
||||||
change do
|
|
||||||
create_table(:users) do
|
|
||||||
primary_key :id
|
|
||||||
String :name, null: false, unique: true
|
|
||||||
TrueClass :admin
|
|
||||||
column :groups, "text[]"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,11 +0,0 @@
|
||||||
Sequel.migration do
|
|
||||||
change do
|
|
||||||
create_table(:points) do
|
|
||||||
# primary_key :id
|
|
||||||
String :assigned_to
|
|
||||||
String :assigned_by
|
|
||||||
String :type
|
|
||||||
DateTime :created_at
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,12 +0,0 @@
|
||||||
Sequel.migration do
|
|
||||||
change do
|
|
||||||
create_table(:messages) do
|
|
||||||
primary_key :id
|
|
||||||
String :author
|
|
||||||
String :dest
|
|
||||||
String :content
|
|
||||||
DateTime :created_at
|
|
||||||
DateTime :read_at
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,14 +0,0 @@
|
||||||
Sequel.migration do
|
|
||||||
change do
|
|
||||||
create_table(:emails) do
|
|
||||||
primary_key :id
|
|
||||||
String :authname
|
|
||||||
String :address
|
|
||||||
DateTime :created_at
|
|
||||||
Integer :usage
|
|
||||||
Bool :primary, default: false
|
|
||||||
|
|
||||||
index [:address], unique: true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,14 +0,0 @@
|
||||||
Sequel.migration do
|
|
||||||
change do
|
|
||||||
create_table(:random_sentences) do
|
|
||||||
primary_key :id
|
|
||||||
String :author
|
|
||||||
String :trigger
|
|
||||||
String :content
|
|
||||||
Bool :enabled, default: true
|
|
||||||
DateTime :created_at
|
|
||||||
|
|
||||||
index :trigger, unique: true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,10 +0,0 @@
|
||||||
Sequel.migration do
|
|
||||||
change do
|
|
||||||
create_table(:eips) do
|
|
||||||
primary_key :id
|
|
||||||
String :author
|
|
||||||
String :title
|
|
||||||
DateTime :created_at
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,70 +0,0 @@
|
||||||
class Base
|
|
||||||
|
|
||||||
def find_and_exec(m, name)
|
|
||||||
u = User.where(name: name).first
|
|
||||||
if u
|
|
||||||
yield u
|
|
||||||
else
|
|
||||||
m.reply "No such user '#{name}'"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.cmd_allowed? m, groups=["admin"], verbose=true
|
|
||||||
user = User.where(name: m.user.authname).where("groups @> '{#{groups.join(',')}}'").first
|
|
||||||
if user.nil?
|
|
||||||
m.reply "No authorized" if verbose
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def cmd_allowed? m, groups=["admin"], verbose=true
|
|
||||||
Base.cmd_allowed?(m, groups, verbose)
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_register m
|
|
||||||
return m.reply "You are not connected" if m.user.authname.nil?
|
|
||||||
begin
|
|
||||||
admin = (User.count == 0)
|
|
||||||
u = User.create(name: m.user.authname,
|
|
||||||
admin: admin,
|
|
||||||
groups: [admin ? 'admin' : 'default'])
|
|
||||||
m.reply "Welcome ##{u.id} #{u.name}"
|
|
||||||
rescue => _
|
|
||||||
m.reply "Cannot register #{m.user.authname}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_ls m
|
|
||||||
c = User.count
|
|
||||||
m.reply User.limit(20).all.map(&:name).join(', ')
|
|
||||||
if c > 20
|
|
||||||
m.reply "And #{c-20} more"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_group_ls m, name
|
|
||||||
cmd_allowed? m
|
|
||||||
find_and_exec(m, name) do |u|
|
|
||||||
m.reply u.groups.join(', ')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_group_add m, name, group
|
|
||||||
cmd_allowed? m
|
|
||||||
find_and_exec(m, name) do |u|
|
|
||||||
u.update(groups: (u.groups + [group]))
|
|
||||||
m.reply "group #{group} added to #{u.name}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_group_rm m, name, group
|
|
||||||
cmd_allowed? m
|
|
||||||
find_and_exec(m, name) do |u|
|
|
||||||
u.update(groups: (u.groups - [group]))
|
|
||||||
m.reply "group #{group} removed from #{u.name}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,68 +0,0 @@
|
||||||
class CeQueTuDisNAAucunSens < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/^[^!].+$/, use_prefix: false, method: :say_random_sentence)
|
|
||||||
match(/^!random_sentence register ([^|]+)\|(.+)/, use_prefix: false, method: :register_trigger)
|
|
||||||
match(/^!random_sentence remove (.+)/, use_prefix: false, method: :remove_trigger)
|
|
||||||
|
|
||||||
HELP = ["!random_sentence register trigger | content",
|
|
||||||
"!random_sentence remove trigger" ]
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def cmd_allowed? m
|
|
||||||
return Base.cmd_allowed? m, ["random_sentence"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def say_random_sentence m
|
|
||||||
trigger = I18n.transliterate(m.message).strip
|
|
||||||
r = Base::DB[:random_sentences].where(enabled: true).where('? ~* "trigger"', trigger).select(:content).first
|
|
||||||
return if r.nil?
|
|
||||||
m.reply r[:content].split(' ').shuffle.join(' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
def say_random m
|
|
||||||
m.reply %w(ce que tu dis n'a aucun sens).shuffle.join(' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
def register_trigger m, t, c
|
|
||||||
return if not cmd_allowed? m
|
|
||||||
t = t.triggerize
|
|
||||||
begin
|
|
||||||
Base::DB[:random_sentences].insert(trigger: t,
|
|
||||||
content: c.strip,
|
|
||||||
author: m.user.authname,
|
|
||||||
created_at: Time.now.utc)
|
|
||||||
m.reply "The trigger \"#{t.strip}\" will raise \"#{c.strip}\""
|
|
||||||
rescue => _err
|
|
||||||
m.reply "Error. Cannot register this trigger"
|
|
||||||
m.reply _err
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_trigger m, t
|
|
||||||
return if not cmd_allowed? m
|
|
||||||
t = t.triggerize
|
|
||||||
n = Base::DB[:random_sentences].where(trigger: t).delete
|
|
||||||
m.reply "Deleted #{n} trigger"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class String
|
|
||||||
def triggerize
|
|
||||||
t = self.dup
|
|
||||||
t = I18n.transliterate(t).strip
|
|
||||||
t = Regexp.quote(t)
|
|
||||||
t.gsub!(/((a)a+)/i, '\2') # ... i know :(
|
|
||||||
t.gsub!(/((e)e+)/i, '\2')
|
|
||||||
t.gsub!(/((i)i+)/i, '\2')
|
|
||||||
t.gsub!(/((o)o+)/i, '\2')
|
|
||||||
t.gsub!(/((u)u+)/i, '\2')
|
|
||||||
t.gsub!(/((y)y+)/i, '\2')
|
|
||||||
t.gsub!(/([aeiouy])/, '\1+')
|
|
||||||
# TODO: not only " " but also ponctuation etc.
|
|
||||||
t = "^(.* )?#{t}( .*)?$"
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
end
|
|
7
plugins/coupon_login.yml.example
Normal file
7
plugins/coupon_login.yml.example
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is independent of /modules_config.yml because it should stay private
|
||||||
|
creditentials:
|
||||||
|
username: login
|
||||||
|
password: pass
|
||||||
|
organisation: orga
|
||||||
|
api_url: https://api.pathwar.net/
|
||||||
|
api_coupon_url: https://api.pathwar.net/organization-coupons/
|
78
plugins/coupons.rb
Normal file
78
plugins/coupons.rb
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#encoding: utf-8
|
||||||
|
|
||||||
|
require 'uri'
|
||||||
|
require 'net/http'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
module BotpopPlugins
|
||||||
|
module Coupons
|
||||||
|
|
||||||
|
COUPON_REGEXP = "[A-Fa-f0-9]{32}"
|
||||||
|
MATCH = lambda do |parent, plugin|
|
||||||
|
# parent.on :message, /coupon(.+)?: .+/ do |m| plugin.exec_coupon m end
|
||||||
|
parent.on :message, /.*#{COUPON_REGEXP}.*/ do |m| plugin.exec_coupon_somewhere m end
|
||||||
|
end
|
||||||
|
# HELP = ["coupon: [...]"]
|
||||||
|
HELP = []
|
||||||
|
CONFIG = Botpop::CONFIG['coupons'] || raise(MissingConfigurationZone, 'coupons')
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
|
|
||||||
|
if ENABLED
|
||||||
|
SECRET_CONFIG = YAML.load_file('plugins/coupon_login.yml')['creditentials']
|
||||||
|
USER = SECRET_CONFIG['username']
|
||||||
|
PASS = SECRET_CONFIG['password']
|
||||||
|
ORGA = SECRET_CONFIG['organisation']
|
||||||
|
APIU = SECRET_CONFIG['api_coupon_url']
|
||||||
|
URL = URI(APIU)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_coupon m
|
||||||
|
coupon = m.params[1..-1].join(' ').gsub(/(coupon(.+)?:)/, '').split.first
|
||||||
|
coupon = coupon.gsub(/[^A-z0-9\.\-_]/, '') # secure a little
|
||||||
|
coupon
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_coupons_somewhere m
|
||||||
|
coupons = m.params[1..-1].join(' ').scan(/#{COUPON_REGEXP}/)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.send_coupon coupon
|
||||||
|
@http ||= Net::HTTP.new(URL.host, URL.port)
|
||||||
|
@http.use_ssl = true
|
||||||
|
# http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||||
|
request = Net::HTTP::Post.new(URL)
|
||||||
|
request.add_field('Content-Type', 'application/json')
|
||||||
|
request.basic_auth USER, PASS
|
||||||
|
request.body = {'coupon' => coupon, 'organization' => ORGA}.to_json
|
||||||
|
response = @http.request(request)
|
||||||
|
@response = response
|
||||||
|
@request = request
|
||||||
|
response
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.validate_coupon m, coupon
|
||||||
|
begin
|
||||||
|
response = send_coupon coupon
|
||||||
|
valid_response = response.code[0] == '2'
|
||||||
|
str = "#{coupon} " + (valid_response ? 'validated' : "failed (#{response.code})")
|
||||||
|
m.reply coupon if CONFIG['display_coupons']
|
||||||
|
rescue => e
|
||||||
|
m.reply "#{coupon} buggy"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# `curl https://api.pathwar.net/organization-coupons/#{coupon} -u '#{USER}:#{PASS}' -X GET`
|
||||||
|
def self.exec_coupon m
|
||||||
|
coupon = get_coupon m
|
||||||
|
validate_coupon m, coupon
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_coupon_somewhere m
|
||||||
|
coupons = get_coupons_somewhere m
|
||||||
|
coupons.each do |coupon|
|
||||||
|
validate_coupon m, coupon
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,12 +0,0 @@
|
||||||
class Character
|
|
||||||
|
|
||||||
attr_accessor :carac, :skills, :hp, :classes, :bab
|
|
||||||
def initialize(str, dex, con, int, wiz, cha, opt={})
|
|
||||||
@carac = {str: str, dex: dex, con: con, int: int, wiz: wiz, cha: cha}
|
|
||||||
@skills = {}
|
|
||||||
@hp = opt[:hp] || nil
|
|
||||||
@classes = opt[:classes] || {}
|
|
||||||
@bab = opt[:bab] || [0]
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,98 +0,0 @@
|
||||||
class FrozenDice
|
|
||||||
attr_reader :min, :max, :values, :nb, :faces
|
|
||||||
|
|
||||||
def initialize arg
|
|
||||||
if arg.is_a? String
|
|
||||||
v = arg.match(/^(?<nb>\d+)d(?<faces>\d+)$/i)
|
|
||||||
if v
|
|
||||||
set_rolldice v
|
|
||||||
else
|
|
||||||
raise ArgumentError unless arg.match(/^\d+$/)
|
|
||||||
set_value arg.to_i
|
|
||||||
end
|
|
||||||
elsif arg.is_a? Integer
|
|
||||||
set_value arg
|
|
||||||
else
|
|
||||||
raise ArgumentError
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def throw
|
|
||||||
@nb.times.map{ rand(@values) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def test
|
|
||||||
self.throw.inject(&:+)
|
|
||||||
end
|
|
||||||
|
|
||||||
def mean
|
|
||||||
v = values.to_a
|
|
||||||
if v.size % 2 == 0
|
|
||||||
(v[v.size / 2 - 1] + v[v.size / 2]) * 0.5
|
|
||||||
else
|
|
||||||
v[v.size / 2]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def set_rolldice v
|
|
||||||
@nb, @faces = v[:nb].to_i, v[:faces].to_i
|
|
||||||
@max = @faces
|
|
||||||
@min = 1
|
|
||||||
@values = @min..@max
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_value v
|
|
||||||
@nb = 1
|
|
||||||
@faces = v
|
|
||||||
@min = @faces
|
|
||||||
@max = @faces
|
|
||||||
@values = @min..@max
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class Dice
|
|
||||||
attr_accessor :bonus, :dices
|
|
||||||
|
|
||||||
def initialize *arg
|
|
||||||
@dices = []
|
|
||||||
arg.each do |a1|
|
|
||||||
a1.gsub!(" ", "")
|
|
||||||
a1.split(/[+ ]/).each do |a2|
|
|
||||||
@dices << FrozenDice.new(a2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def min
|
|
||||||
@dices.map do |dice|
|
|
||||||
dice.min
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def mean
|
|
||||||
@dices.map do |dice|
|
|
||||||
dice.mean
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def max
|
|
||||||
@dices.map do |dice|
|
|
||||||
dice.max
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def throw
|
|
||||||
@dices.map do |dice|
|
|
||||||
dice.throw
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test
|
|
||||||
@dices.map do |dice|
|
|
||||||
dice.test
|
|
||||||
end.inject(&:+)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,12 +0,0 @@
|
||||||
require_relative 'Character'
|
|
||||||
|
|
||||||
class Warrior < Character
|
|
||||||
|
|
||||||
def initialize str, *arg
|
|
||||||
super(str, 10, 10, 10, 10, 10, *arg)
|
|
||||||
end
|
|
||||||
|
|
||||||
def str; carac[:str]; end
|
|
||||||
def bstr; (str - 10) / 2; end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,84 +0,0 @@
|
||||||
require_relative 'Dice'
|
|
||||||
require_relative 'Warrior'
|
|
||||||
|
|
||||||
class Weapon
|
|
||||||
attr_reader :from, :degats, :opt, :bonus
|
|
||||||
|
|
||||||
def initialize from, degats, opt, bonus, attack_opt={}
|
|
||||||
@from = from
|
|
||||||
@bonus = from.bab.map{|e| e + bonus}
|
|
||||||
@degats = Dice.new(degats + "+#{(from.bstr * 1.5).ceil}")
|
|
||||||
@hands = opt[:hands] || 1
|
|
||||||
@max = attack_opt[:max] || Float::INFINITY
|
|
||||||
end
|
|
||||||
|
|
||||||
def min
|
|
||||||
@degats.min
|
|
||||||
end
|
|
||||||
|
|
||||||
def max
|
|
||||||
@degats.max
|
|
||||||
end
|
|
||||||
|
|
||||||
def mean
|
|
||||||
@degats.mean
|
|
||||||
end
|
|
||||||
|
|
||||||
def test
|
|
||||||
@degats.test
|
|
||||||
end
|
|
||||||
|
|
||||||
def mean_p(ca=20.0)
|
|
||||||
d = @degats.mean.inject(&:+)
|
|
||||||
p(ca).map do |b|
|
|
||||||
(b * d).round(4)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def p(ca=20.0)
|
|
||||||
@bonus.map do |b|
|
|
||||||
((b + from.bstr) / ca.to_f).round(4)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def mean_p_total(ca=20.0)
|
|
||||||
mean_p(ca).inject(&:+).round(4)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s(ca=20)
|
|
||||||
"mean: #{mean} * #{p(ca)} => #{mean_p(ca)} = #{mean_p_total(ca)}"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
if __FILE__ == $0
|
|
||||||
alteration = 2
|
|
||||||
taille = -2
|
|
||||||
bonus = alteration + taille
|
|
||||||
|
|
||||||
epees = []
|
|
||||||
normal = Warrior.new 18, {bab: [7, 1]}
|
|
||||||
epees << ["normal", Weapon.new(normal, "4d6+2", {hands: 2}, bonus)]
|
|
||||||
|
|
||||||
rage = Warrior.new 19+4, {bab: [7, 1]}
|
|
||||||
epees << ["rage", Weapon.new(rage, "4d6+2", {hands: 2}, bonus)]
|
|
||||||
|
|
||||||
fren = Warrior.new 19+6, {bab: [7, 1]}
|
|
||||||
epees << ["frenesie", Weapon.new(fren, "4d6+2", {hands: 2}, bonus)]
|
|
||||||
|
|
||||||
ra_fr = Warrior.new 19+4+6, {bab: [7, 7, 1]}
|
|
||||||
epees << ["rage+frenesie", Weapon.new(ra_fr, "4d6+2", {hands: 2}, bonus)]
|
|
||||||
|
|
||||||
ra_fr_so = Warrior.new 19+6+4, {bab: [7, 7, 1]}
|
|
||||||
epees << ["rage+frenesie+sorciere", Weapon.new(ra_fr_so, "4d6+2+5+1d6", {hands: 2}, bonus)]
|
|
||||||
|
|
||||||
ra_fr_so_buff = Warrior.new 19+6+4+4, {bab: [7, 7, 1]}
|
|
||||||
epees << ["rage+frenesie+sorciere+taureau+benediction", Weapon.new(ra_fr_so, "4d6+2+5+1d6", {hands: 2}, bonus+1)]
|
|
||||||
|
|
||||||
ra_fr_so_buff_char = Warrior.new 19+6+4+4, {bab: [7, 7]}
|
|
||||||
epees << ["rage+frenesie+sorciere+taureau+benediction+charge", Weapon.new(ra_fr_so, "4d6+2+5+1d6", {hands: 2}, bonus+1+2, {max: 2})]
|
|
||||||
|
|
||||||
epees = Hash[epees]
|
|
||||||
require 'pry'
|
|
||||||
binding.pry
|
|
||||||
end
|
|
|
@ -1,22 +0,0 @@
|
||||||
require_relative 'dice/Dice'
|
|
||||||
require_relative 'dice/Weapon'
|
|
||||||
require_relative 'dice/Character'
|
|
||||||
require_relative 'dice/Warrior'
|
|
||||||
|
|
||||||
class Diceroller < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/!roll (.+)/, use_prefix: false, method: :exec_roll)
|
|
||||||
|
|
||||||
HELP = ["!roll (d20 ...)"]
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
CHARACTER = Warrior.new 10, {bab: [0]}
|
|
||||||
|
|
||||||
def exec_roll(m, roll)
|
|
||||||
val = Weapon.new(CHARACTER, roll, {hands: 1}, 0).test
|
|
||||||
m.reply "Roll ... '#{roll}' ... #{val}"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,35 +0,0 @@
|
||||||
class Eip < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/!eip add (.*)/, use_prefix: false, method: :exec_add)
|
|
||||||
match(/!eip ls/, use_prefix: false, method: :exec_ls)
|
|
||||||
match(/!eip (\d+)/, use_prefix: false, method: :exec_id)
|
|
||||||
|
|
||||||
HELP = ["!eip add ...", "!eip ls", "!eip id"]
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def exec_add(m, title)
|
|
||||||
begin
|
|
||||||
Base::DB[:eips].insert(author: m.user.authname,
|
|
||||||
title: title,
|
|
||||||
created_at: Time.now)
|
|
||||||
m.reply "Ok ! #{title} is a new eip"
|
|
||||||
rescue
|
|
||||||
m.reply "Err"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_id(m, id)
|
|
||||||
all = Base::DB[:eips].where(id: Integer(id)).first
|
|
||||||
m.reply all[:title] rescue m.reply("no such id")
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_ls(m)
|
|
||||||
all = Base::DB[:eips].limit(3).reverse.all
|
|
||||||
all.each{|e| m.reply e[:title]}
|
|
||||||
n = Base::DB[:eips].count
|
|
||||||
m.reply("There is #{n} elements")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,20 +0,0 @@
|
||||||
require 'tor257/core'
|
|
||||||
require 'base64'
|
|
||||||
|
|
||||||
class Encrypt < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/^!tor257 (c|d) (\w+) (.+)/, use_prefix: false, method: :exec_tor257)
|
|
||||||
|
|
||||||
HELP = ["!tor257 <c|d> keyphrase data"]
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def exec_tor257 m, type, k, d
|
|
||||||
d = Base64.decode64(d.strip) if type == 'd'
|
|
||||||
e = Tor257::Message.new(d).encrypt(Tor257::Key.new(k)).to_s
|
|
||||||
e = Base64.encode64(e) if type == 'c'
|
|
||||||
m.reply e
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
30
plugins/epitech.rb
Normal file
30
plugins/epitech.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#encoding: utf-8
|
||||||
|
|
||||||
|
module BotpopPlugins
|
||||||
|
module Epitech
|
||||||
|
NAME = self.to_s.split(':').last
|
||||||
|
|
||||||
|
MATCH = lambda do |parent, plugin|
|
||||||
|
parent.on :message, /!admin/ do |m| plugin.exec_admin m end
|
||||||
|
parent.on :message, /!bocal/ do |m| plugin.exec_bocal m end
|
||||||
|
parent.on :message, /!astek/ do |m| plugin.exec_astek m end
|
||||||
|
end
|
||||||
|
HELP = ["!admin", "!bocal", "!astek"]
|
||||||
|
CONFIG = Botpop::CONFIG['epitech'] || raise(MissingConfigurationZone, NAME)
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
|
ASTEKS = CONFIG['asteks'] || []
|
||||||
|
|
||||||
|
def self.exec_admin m
|
||||||
|
m.reply "Afk"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_bocal m
|
||||||
|
m.reply "Bataaaaaaaards !!"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_astek m
|
||||||
|
m.reply "Enculéééééééés !!"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,14 +1,19 @@
|
||||||
class MyFury < Botpop::Plugin
|
#encoding: utf-8
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/!whatkingofanimal.*/, use_prefix: false, method: :exec_whatkingofanimal)
|
module BotpopPlugins
|
||||||
|
module MyFuryPlugin
|
||||||
|
NAME = self.to_s.split(':').last
|
||||||
|
|
||||||
HELP = ["!whatkingofanimal", "!animallist", "!checkanimal [type]"]
|
MATCH = lambda do |parent, plugin|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
parent.on :message, /!whatkingofanimal.*/ do |m| plugin.exec_whatkingofanimal m end
|
||||||
CONFIG = config
|
end
|
||||||
|
HELP = ["!whatkingofanimal", "!animallist", "!checkanimal [type]"]
|
||||||
|
CONFIG = Botpop::CONFIG['example'] || raise(MissingConfigurationZone, NAME)
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? false : CONFIG['enable']
|
||||||
|
|
||||||
|
def self.exec_whatkingofanimal m
|
||||||
|
m.reply "Die you son of a" + ["lion", "pig", "red panda"].shuffle.first + " !!"
|
||||||
|
end
|
||||||
|
|
||||||
def exec_whatkingofanimal m
|
|
||||||
m.reply "Die you son of a" + ["lion", "pig", "red panda"].sample + " !!"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,111 +1,67 @@
|
||||||
class IAmAlive < Botpop::Plugin
|
# encoding: utf-8
|
||||||
include Cinch::Plugin
|
|
||||||
include Botpop::Plugin::Database
|
|
||||||
|
|
||||||
match(/^[^!].*/, use_prefix: false, method: :register_entry)
|
# 4.times {puts "=".yellow * 74}
|
||||||
match(/^[^!].*/, use_prefix: false, method: :react_on_entry)
|
# puts "THE IAMALIVE PLUGINS IN INSANE. DISABLE BY USING --plugin-disable iamalive".red
|
||||||
match(/^!iaa reac(tivity)?$/, use_prefix: false, method: :get_reactivity)
|
# 4.times {puts "=".yellow * 74}
|
||||||
match(/^!iaa reac(tivity)? \d{1,3}$/, use_prefix: false, method: :set_reactivity)
|
# sleep 1
|
||||||
match(/^!iaa learn$/, use_prefix: false, method: :set_mode_learn)
|
|
||||||
match(/^!iaa live$/, use_prefix: false, method: :set_mode_live)
|
|
||||||
match(/^!iaa mode$/, use_prefix: false, method: :get_mode)
|
|
||||||
match(/^!iaa stats?$/, use_prefix: false, method: :get_stats)
|
|
||||||
match(/^!iaa forget( (\d+ )?(.+))?/, use_prefix: false, method: :forget)
|
|
||||||
match(/^!iaa last( \w+)?$/, use_prefix: false, method: :get_last)
|
|
||||||
|
|
||||||
CONFIG = config(:safe => true)
|
module BotpopPlugins
|
||||||
ENABLED = CONFIG['enable'] || false
|
module IAmAlive
|
||||||
HELP = ["!iaa reac", "!iaa reac P", "!iaa learn", "!iaa live", "!iaa mode",
|
|
||||||
"!iaa stats", "!iaa forget (Nx SENTENCE)", "!iaa last (nick)",
|
|
||||||
"!iaa user [add/remove/list]"]
|
|
||||||
|
|
||||||
@@mode = config['default_mode'].to_sym
|
MATCH = lambda do |parent, plugin|
|
||||||
@@reactivity = config['reactivity'] || 50
|
parent.on :message, /.+/ do |m| plugin.exec_learn m end
|
||||||
|
parent.on :message, /.+/ do |m| plugin.exec_speak m end
|
||||||
def cmd_allowed? m
|
parent.on :message, "!iaa clean" do |m| plugin.exec_clean m end
|
||||||
return Base.cmd_allowed? m, ["iaa"]
|
|
||||||
end
|
|
||||||
|
|
||||||
if ENABLED
|
|
||||||
DB_CONFIG = self.db_config = CONFIG['database']
|
|
||||||
DB = self.db_connect!
|
|
||||||
require_relative 'iamalive/entry'
|
|
||||||
end
|
|
||||||
|
|
||||||
def register_entry m
|
|
||||||
Entry.create(user: (m.user.authname || m.user.nick), message: m.message, channel: m.channel.to_s)
|
|
||||||
forget_older! if rand(1..100) == 100
|
|
||||||
end
|
|
||||||
|
|
||||||
def react_on_entry m
|
|
||||||
return if @@mode != :live
|
|
||||||
e = Entry.where('LOWER(message) = LOWER(?)', m.message).select(:id).all.map(&:id).map{|x| x+1}
|
|
||||||
if @@reactivity > rand(1..100)
|
|
||||||
answer_to(m, e)
|
|
||||||
end
|
end
|
||||||
end
|
HELP = ["I'm learning from you"]
|
||||||
|
|
||||||
private
|
CONFIG = Botpop::CONFIG['iamalive'] || raise(MissingConfigurationZone, 'iamalive')
|
||||||
def answer_to m, e
|
ENABLED = CONFIG['enable'].nil? ? false : CONFIG['enable']
|
||||||
a = Entry.where(id: e).to_a.sample
|
if ENABLED
|
||||||
if not a.nil?
|
DATABASE_FILE = CONFIG['database_file'] || raise(MissingConfigurationEntry, 'iamalive::database_file')
|
||||||
sleep(a.message.split.size.to_f / 10)
|
File.open(DATABASE_FILE, 'r') rescue init_database
|
||||||
m.reply a.message
|
# DISABLED MAY BE CONFIGURED, DEFAULT IS TRUE
|
||||||
Entry.create(user: "self", message: a.message, channel: m.channel.to_s)
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def forget_older!
|
def self.init_database
|
||||||
log "Forget the older entry"
|
f = File.open(DATABASE_FILE, 'w')
|
||||||
Entry.first.delete
|
f.write("learn:\n")
|
||||||
end
|
f.close
|
||||||
public
|
|
||||||
|
|
||||||
def get_reactivity m
|
|
||||||
m.reply "Current reactivity: #{@@reactivity}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_reactivity m
|
|
||||||
return if not cmd_allowed? m
|
|
||||||
@@reactivity = m.message.split[2].to_i
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_mode_learn m
|
|
||||||
return if not cmd_allowed? m
|
|
||||||
@@mode = :learn
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_mode_live m
|
|
||||||
return if not cmd_allowed? m
|
|
||||||
@@mode = :live
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_mode m
|
|
||||||
m.reply "Current mode: #{@@mode}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_stats m
|
|
||||||
m.reply "Registered sentences: #{Entry.count}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def forget m, arguments, nb, what
|
|
||||||
return if not cmd_allowed? m
|
|
||||||
if arguments.nil?
|
|
||||||
last = Entry.where(channel: m.channel.to_s, user: "self").last
|
|
||||||
m.reply last ? "\"#{last.message}\" Forgotten" : "Nop"
|
|
||||||
last.delete
|
|
||||||
else
|
|
||||||
nb = nb.to_i if not nb.nil?
|
|
||||||
nb ||= Entry.where(message: what).count
|
|
||||||
n = Entry.where(message: what).order_by(:id).reverse.limit(nb).map(&:delete).size rescue 0
|
|
||||||
m.reply "(#{n}x) \"#{what}\" Forgotten"
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def get_last m, user
|
def self.open_database
|
||||||
user.strip! if user
|
begin
|
||||||
last = Entry.where(channel: m.channel.to_s, user: (user || "self")).last
|
@iamalive_db = YAML.load_file(DATABASE_FILE)['learn'].to_a
|
||||||
m.reply "#{user}: #{last ? last.message : 'no message found'}"
|
rescue
|
||||||
end
|
init_database
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Store in a database
|
||||||
|
def self.exec_learn m
|
||||||
|
line = m.params[1..-1].join(' ').to_yaml.gsub("--", " ").gsub("...\n", "")
|
||||||
|
return if line.include?("VERSION") or line.match /\A["']?!/ or line.match(/\Ahttp/)
|
||||||
|
f = File.open(DATABASE_FILE, 'a')
|
||||||
|
f.write(line)
|
||||||
|
f.close
|
||||||
|
# m.reply "Learn: #{line}"
|
||||||
|
end
|
||||||
|
|
||||||
|
PROBA = 6
|
||||||
|
def self.exec_speak m
|
||||||
|
if Random.rand(PROBA).zero?
|
||||||
|
open_database
|
||||||
|
i = Random.rand(@iamalive_db.size)
|
||||||
|
m.reply @iamalive_db[i]
|
||||||
|
else
|
||||||
|
# m.reply "no reply"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_clean m
|
||||||
|
init_database
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
# I Am Alive
|
|
||||||
|
|
||||||
I am alive is a plugin, that allows to bot to answer to me :)
|
|
||||||
|
|
||||||
## Initialization
|
|
||||||
|
|
||||||
### Database
|
|
||||||
|
|
||||||
Firstly, create the database and migrate it. To do this, use the following command.
|
|
||||||
In the ``modules_config.yml`` file, configure it for your engine.
|
|
||||||
As it use sequel engine, it is compatible with sqlite, mysql, postgres, etc.
|
|
||||||
Checkout the [sequel documentaiton](http://sequel.jeremyevans.net/documentation.html) for more informations.
|
|
||||||
Then, execute one of two:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sequel -m plugins/iamalive/migrations sqlite://plugins/iamalive/db.sqlite3
|
|
||||||
sequel -m plugins/iamalive/migrations postgres://root:toor@localhost:5432/botpop_iamalive
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
You can change the name of the database via the global configuration file (see the example).
|
|
||||||
|
|
||||||
### User / Admin
|
|
||||||
|
|
||||||
Only authorized users have the rights to administrate the iaa plugin.
|
|
||||||
Only when there is no administrator (by default), you can use the command "!iaa user add NICK" to add your NICK to the database.
|
|
||||||
Be sure you have a protected identity.
|
|
||||||
|
|
||||||
Then, only administrators can add / remove admin from the list.
|
|
|
@ -1,9 +0,0 @@
|
||||||
require 'sequel'
|
|
||||||
|
|
||||||
class IAmAlive
|
|
||||||
|
|
||||||
class Admin < Sequel::Model
|
|
||||||
set_dataset DB[:admins]
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,31 +0,0 @@
|
||||||
require 'sequel'
|
|
||||||
|
|
||||||
class IAmAlive
|
|
||||||
|
|
||||||
class IAAMessage < String
|
|
||||||
|
|
||||||
def initialize *arg
|
|
||||||
super(*arg)
|
|
||||||
self.strip!
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class Entry < Sequel::Model
|
|
||||||
def before_create
|
|
||||||
self.created_at ||= Time.now
|
|
||||||
self.message.strip!
|
|
||||||
self.message_origin = self.message
|
|
||||||
self.message = IAAMessage.new(self.message).to_s
|
|
||||||
super
|
|
||||||
end
|
|
||||||
set_dataset DB[:entries]
|
|
||||||
|
|
||||||
def self.anwser(message)
|
|
||||||
Entry.where('LOWER(message) = LOWER(?)', m.message.to_iaa_message).
|
|
||||||
select(:id).all.map(&:id).map{|x| x+1}
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,12 +0,0 @@
|
||||||
Sequel.migration do
|
|
||||||
change do
|
|
||||||
create_table(:entries) do
|
|
||||||
primary_key :id
|
|
||||||
String :user, null: false
|
|
||||||
String :channel, null: false
|
|
||||||
String :message, null: false, text: true
|
|
||||||
String :message_origin, null: false, text: true
|
|
||||||
DateTime :created_at
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
Sequel.migration do
|
|
||||||
change do
|
|
||||||
create_table(:admins) do
|
|
||||||
primary_key :id
|
|
||||||
String :user, null: false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
41
plugins/intranet.rb
Normal file
41
plugins/intranet.rb
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#encoding: utf-8
|
||||||
|
|
||||||
|
module BotpopPlugins
|
||||||
|
module Intranet
|
||||||
|
|
||||||
|
MATCH = lambda do |parent, plugin|
|
||||||
|
parent.on :message, "!intra" do |m| plugin.exec_intra m end
|
||||||
|
parent.on :message, "!intra on" do |m| plugin.exec_intra_on m end
|
||||||
|
parent.on :message, "!intra off" do |m| plugin.exec_intra_off m end
|
||||||
|
end
|
||||||
|
HELP = ["!intra <on, off>"]
|
||||||
|
CONFIG = Botpop::CONFIG['intranet'] || raise(MissingConfigurationZone, 'intranet')
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
|
|
||||||
|
def self.exec_intra m
|
||||||
|
m.reply BotpopBuiltins.intra_state rescue m.reply "I'm buggy. Sorry"
|
||||||
|
end
|
||||||
|
|
||||||
|
INTRA_PING_SLEEP = 30
|
||||||
|
def self.exec_intra_on m
|
||||||
|
@intra ||= Mutex.new
|
||||||
|
if @intra.try_lock
|
||||||
|
@intra_on = true
|
||||||
|
m.reply "INTRANET SPY ON"
|
||||||
|
while @intra_on
|
||||||
|
m.reply BotpopBuiltins.intra_state rescue return @intra.unlock
|
||||||
|
sleep INTRA_PING_SLEEP
|
||||||
|
end
|
||||||
|
@intra.unlock
|
||||||
|
else
|
||||||
|
m.reply "INTRA SPY ALREADY ON"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_intra_off m
|
||||||
|
m.reply @intra_on ? "INTRA SPY OFF" : "INTRA SPY ALREADY OFF"
|
||||||
|
@intra_on = false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,27 +0,0 @@
|
||||||
#encoding: utf-8
|
|
||||||
|
|
||||||
class Kick < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/!k (.+)/, use_prefix: false, method: :exec_kick)
|
|
||||||
match(/!kick (.+)/, use_prefix: false, method: :exec_kick)
|
|
||||||
match(/!k ([^|]+)\|(.+)/, use_prefix: false, method: :exec_kick_message)
|
|
||||||
match(/!kick ([^|]+)\|(.+)/, use_prefix: false, method: :exec_kick_message)
|
|
||||||
|
|
||||||
HELP = ["!kick nickname <message>"]
|
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def exec_kick m, victim
|
|
||||||
len = CONFIG["list"].length - 1
|
|
||||||
msg = CONFIG["list"][rand(0..len)]
|
|
||||||
m.channel.kick(victim, msg)
|
|
||||||
m.reply "Bye bye " + victim
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_kick_message m, victim, reason
|
|
||||||
m.channel.kick(victim, reason)
|
|
||||||
m.reply "Bye bye " + victim
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,68 +0,0 @@
|
||||||
#encoding: utf-8
|
|
||||||
|
|
||||||
class Log < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match /users$/, use_prefix: true, method: :exec_list_user
|
|
||||||
match /remove .+$/, use_prefix: true, method: :exec_remove_user
|
|
||||||
match /add .+$/, use_prefix: true, method: :exec_add_user
|
|
||||||
match /clean$/, use_prefix: true, method: :exec_clean
|
|
||||||
match /status$/, use_prefix: true, method: :exec_status
|
|
||||||
match /enable$/, use_prefix: true, method: :exec_log_enable
|
|
||||||
match /.+/, use_prefix: false, method: :exec_log
|
|
||||||
|
|
||||||
HELP = ["!log enable", "!log add", "!log remove", "!log users", "!log clean", "!log status"]
|
|
||||||
CONFIG = config
|
|
||||||
ENABLED = CONFIG['enable'].nil? ? false : CONFIG['enable']
|
|
||||||
USER_CONFIG = "plugins/log_user.yml"
|
|
||||||
USERS = YAML.load_file(USER_CONFIG) || raise(MissingConfigurationZone, USER_CONFIG)
|
|
||||||
|
|
||||||
@@log_user_list = USERS["list"]
|
|
||||||
@@log_enabled = CONFIG["default_started"]
|
|
||||||
|
|
||||||
def exec_list_user m
|
|
||||||
m.reply @@log_user_list.join(", ")
|
|
||||||
m.reply "no log admin" if @@log_user_list.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_remove_user m
|
|
||||||
return unless is_admin? m
|
|
||||||
m.message.gsub("!log add ", "").split(" ").each do |name|
|
|
||||||
@@log_user_list.delete name unless USERS["list"].include?(name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_add_user m
|
|
||||||
return unless is_admin? m
|
|
||||||
@@log_user_list += m.message.gsub("!log add ", "").split(" ")
|
|
||||||
@@log_user_list.uniq!
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_log_enable m
|
|
||||||
@@log_enabled = !@@log_enabled
|
|
||||||
exec_status m
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_status m
|
|
||||||
m.reply "Log #{@@log_enabled ? :enabled : :disabled}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_clean m
|
|
||||||
return unless is_admin? m
|
|
||||||
File.delete(CONFIG["file"]) rescue nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_log m
|
|
||||||
log(m) if @@log_enabled
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def log m
|
|
||||||
File.open(CONFIG["file"], 'a') {|f| f << (m.user.to_s + ": " + m.message + "\n")}
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_admin? m
|
|
||||||
@@log_user_list.include? m.user.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
74
plugins/logger.rb
Normal file
74
plugins/logger.rb
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#encoding: utf-8
|
||||||
|
|
||||||
|
module BotpopPlugins
|
||||||
|
module Logger
|
||||||
|
NAME = self.to_s.split(':').last
|
||||||
|
|
||||||
|
MATCH = lambda do |parent, plugin|
|
||||||
|
parent.on :message, /!log users/ do |m| plugin.exec_list_user m end
|
||||||
|
parent.on :message, /!log remove .+/ do |m| plugin.exec_remove_user m end
|
||||||
|
parent.on :message, /!log add .+/ do |m| plugin.exec_add_user m end
|
||||||
|
parent.on :message, /!log clean/ do |m| plugin.exec_clean m end
|
||||||
|
parent.on :message, /!log status/ do |m| plugin.exec_status m end
|
||||||
|
parent.on :message, /!log\Z/ do |m| plugin.exec_log_enable m end
|
||||||
|
parent.on :message, /.+/ do |m| plugin.exec_log m end
|
||||||
|
end
|
||||||
|
HELP = ["!log", "!log add", "!log remove", "!log users", "!log clean", "!log status"]
|
||||||
|
CONFIG = Botpop::CONFIG['logger'] || raise(MissingConfigurationZone, NAME)
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? false : CONFIG['enable']
|
||||||
|
USER_CONFIG = "plugins/logger_user.yml"
|
||||||
|
USERS = YAML.load_file(USER_CONFIG) || raise(MissingConfigurationZone, USER_CONFIG)
|
||||||
|
|
||||||
|
@@logger_user_list = USERS["list"]
|
||||||
|
@@logger_enabled = false
|
||||||
|
|
||||||
|
def self.exec_list_user m
|
||||||
|
m.reply @@logger_user_list.join(", ")
|
||||||
|
m.reply "no logger admin" if @@logger_user_list.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_remove_user m
|
||||||
|
return unless is_admin? m
|
||||||
|
m.message.gsub("!log add ", "").split(" ").each do |name|
|
||||||
|
@@logger_user_list.delete name unless USERS["list"].include?(name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_add_user m
|
||||||
|
return unless is_admin? m
|
||||||
|
@@logger_user_list += m.message.gsub("!log add ", "").split(" ")
|
||||||
|
@@logger_user_list.uniq!
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_log_enable m
|
||||||
|
@@logger_enabled = !@@logger_enabled
|
||||||
|
exec_status m
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_status m
|
||||||
|
m.reply "Logger #{@@logger_enabled ? :enabled : :disabled}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_clean m
|
||||||
|
return unless is_admin? m
|
||||||
|
File.delete(CONFIG["file"]) rescue nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_log m
|
||||||
|
log(m) if @@logger_enabled
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def self.log m
|
||||||
|
@@logger_lock ||= Mutex.new
|
||||||
|
@@logger_lock.lock
|
||||||
|
File.open(CONFIG["file"], 'a') {|f| f << (m.user.to_s + ": " + m.message + "\n")} rescue nil
|
||||||
|
@@logger_lock.unlock
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.is_admin? m
|
||||||
|
@@logger_user_list.include? m.user.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,175 +1,178 @@
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
class Network < Botpop::Plugin
|
module BotpopPlugins
|
||||||
include Cinch::Plugin
|
module Network
|
||||||
|
|
||||||
match("!ping", use_prefix: false, method: :exec_ping)
|
MATCH = lambda do |parent, plugin|
|
||||||
match(/!ping #{Botpop::TARGET}\Z/, use_prefix: false, method: :exec_ping_target)
|
parent.on :message, "!ping" do |m| plugin.exec_ping m end
|
||||||
match(/!httping #{Botpop::TARGET}\Z/, use_prefix: false, method: :exec_ping_http)
|
parent.on :message, /!ping #{Botpop::TARGET}\Z/ do |m| plugin.exec_ping_target m end
|
||||||
match(/!dos #{Botpop::TARGET}\Z/, use_prefix: false, method: :exec_dos)
|
parent.on :message, /!httping #{Botpop::TARGET}\Z/ do |m| plugin.exec_ping_http m end
|
||||||
match(/!fok #{Botpop::TARGET}\Z/, use_prefix: false, method: :exec_fok)
|
parent.on :message, /!dos #{Botpop::TARGET}\Z/ do |m| plugin.exec_dos m end
|
||||||
match(/!trace #{Botpop::TARGET}\Z/, use_prefix: false, method: :exec_trace)
|
parent.on :message, /!fok #{Botpop::TARGET}\Z/ do |m| plugin.exec_fok m end
|
||||||
match(/!poke #{Botpop::TARGET}\Z/, use_prefix: false, method: :exec_poke)
|
parent.on :message, /!trace #{Botpop::TARGET}\Z/ do |m| plugin.exec_trace m end
|
||||||
|
parent.on :message, /!poke #{Botpop::TARGET}\Z/ do |m| plugin.exec_poke m end
|
||||||
HELP = ["!ping", "!ping [ip]", "!httping [ip]",
|
|
||||||
"!dos [ip]", "!fok [nick]", "!trace [ip]", "!poke [nick]"]
|
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
private
|
|
||||||
# Conversion of the string to value in ms
|
|
||||||
def self.config_string_to_time(value)
|
|
||||||
value.match(/\d+ms\Z/) ? value.to_f / 100.0 : value.to_f
|
|
||||||
end
|
|
||||||
public
|
|
||||||
|
|
||||||
DOS_DURATION = config['dos_duration'] || '2s'
|
|
||||||
DOS_WAIT_DURATION_STRING = config['dos_wait'] || '5s'
|
|
||||||
DOS_WAIT_DURATION = config_string_to_time DOS_WAIT_DURATION_STRING
|
|
||||||
|
|
||||||
# Trace is complexe. 3 functions used exec_trace_display_lines, exec_trace_with_time, exec_trace
|
|
||||||
TRACE_DURATION_INIT_STRING_DEFAULT = "0.3s"
|
|
||||||
TRACE_DURATION_INIT_STRING = config['trace_duration_init'] || TRACE_DURATION_INIT_STRING_DEFAULT
|
|
||||||
TRACE_DURATION_INCR_STRING_DEFAULT = "0.1s"
|
|
||||||
TRACE_DURATION_INCR_STRING = config['trace_duration_incr'] || TRACE_DURATION_INCR_STRING_DEFAULT
|
|
||||||
TRACE_DURATION_INIT = config_string_to_time TRACE_DURATION_INIT_STRING
|
|
||||||
TRACE_DURATION_INCR = config_string_to_time TRACE_DURATION_INCR_STRING
|
|
||||||
|
|
||||||
# @param what [Net::Ping::External]
|
|
||||||
# @param what [Net::Ping::HTTP]
|
|
||||||
def ping_with m, what
|
|
||||||
ip = Botpop::Builtins.get_ip m
|
|
||||||
p = what.new ip
|
|
||||||
str = p.ping(ip) ? "#{(p.duration*100.0).round 2}ms (#{p.host})" : 'failed'
|
|
||||||
m.reply "#{ip} > #{what.to_s.split(':').last} ping > #{str}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_ping m
|
|
||||||
m.reply "#{m.user} > pong"
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_ping_target m
|
|
||||||
ping_with m, Net::Ping::External
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_ping_http m
|
|
||||||
ping_with m, Net::Ping::HTTP
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_poke m
|
|
||||||
nick = Botpop::Builtins.get_ip_from_nick(m)[:nick]
|
|
||||||
ip = Botpop::Builtins.get_ip_from_nick(m)[:ip]
|
|
||||||
return m.reply "User '#{nick}' doesn't exists" if ip.nil?
|
|
||||||
# Display
|
|
||||||
response = Botpop::Builtins.ping(ip) ? "#{(p.duration*100.0).round 2}ms (#{p.host})" : "failed"
|
|
||||||
m.reply "#{nick} > poke > #{response}"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def dos_check_ip(m, ip)
|
|
||||||
return true if Botpop::Builtins.ping(ip)
|
|
||||||
m.reply "Cannot reach the host '#{ip}'"
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
def dos_replier m, ip, s
|
|
||||||
if s.nil?
|
|
||||||
m.reply "The dos has failed"
|
|
||||||
elsif Botpop::Builtins.ping(ip)
|
|
||||||
m.reply "Sorry, the target is still up !"
|
|
||||||
else
|
|
||||||
m.reply "Target down ! --- #{s}"
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# This function avoid overusage of the resources by using mutex locking.
|
HELP = ["!ping", "!ping [ip]", "!httping [ip]",
|
||||||
# It execute the lamdba function passed as 2sd parameter if resources are ok
|
"!dos [ip]", "!fok [nick]", "!trace [ip]", "!poke [nick]"]
|
||||||
# At the end of the attack, it wait few seconds (configuration) before
|
CONFIG = Botpop::CONFIG['network'] || raise(MissingConfigurationZone, 'network')
|
||||||
# releasing the resources and permit a new attack.
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
#
|
|
||||||
# @arg lambda [Lambda] lambda with one argument (m). It wil be executed
|
private
|
||||||
def dos_execution(m, lambda)
|
# Conversion of the string to value in ms
|
||||||
@dos ||= Mutex.new
|
def self.config_string_to_time(value)
|
||||||
if @dos.try_lock
|
value.match(/\d+ms\Z/) ? value.to_f / 100.0 : value.to_f
|
||||||
lambda.call(m)
|
|
||||||
sleep DOS_WAIT_DURATION
|
|
||||||
@dos.unlock
|
|
||||||
else
|
|
||||||
m.reply "Wait for the end of the last dos"
|
|
||||||
end
|
end
|
||||||
end
|
public
|
||||||
|
|
||||||
def dos_ip(ip)
|
DOS_DURATION = CONFIG['dos_duration'] || '2s'
|
||||||
return Botpop::Builtins.dos(ip, DOS_DURATION).split("\n")[3].to_s rescue nil
|
DOS_WAIT_DURATION_STRING = CONFIG['dos_wait'] || '5s'
|
||||||
end
|
DOS_WAIT_DURATION = config_string_to_time DOS_WAIT_DURATION_STRING
|
||||||
|
|
||||||
def exec_dos m
|
# Trace is complexe. 3 functions used exec_trace_display_lines, exec_trace_with_time, exec_trace
|
||||||
dos_execution m, lambda {|m|
|
TRACE_DURATION_INIT_STRING_DEFAULT = "0.3s"
|
||||||
ip = Botpop::Builtins.get_ip m
|
TRACE_DURATION_INIT_STRING = CONFIG['trace_duration_init'] || TRACE_DURATION_INIT_STRING_DEFAULT
|
||||||
return if not dos_check_ip(m, ip)
|
TRACE_DURATION_INCR_STRING_DEFAULT = "0.1s"
|
||||||
m.reply "Begin attack against #{ip}"
|
TRACE_DURATION_INCR_STRING = CONFIG['trace_duration_incr'] || TRACE_DURATION_INCR_STRING_DEFAULT
|
||||||
s = dos_ip(ip)
|
TRACE_DURATION_INIT = config_string_to_time TRACE_DURATION_INIT_STRING
|
||||||
dos_replier m, ip, s
|
TRACE_DURATION_INCR = config_string_to_time TRACE_DURATION_INCR_STRING
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_fok m
|
# @param what [Net::Ping::External]
|
||||||
dos_execution m, lambda {|m|
|
# @param what [Net::Ping::HTTP]
|
||||||
nick = Botpop::Builtins.get_ip_from_nick(m)[:nick]
|
def self.ping_with m, what
|
||||||
ip = Botpop::Builtins.get_ip_from_nick(m)[:ip]
|
ip = BotpopBuiltins.get_ip m
|
||||||
|
p = what.new ip
|
||||||
|
str = p.ping(ip) ? "#{(p.duration*100.0).round 2}ms (#{p.host})" : 'failed'
|
||||||
|
m.reply "#{ip} > #{what.to_s.split(':').last} ping > #{str}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_ping m
|
||||||
|
m.reply "#{m.user} > pong"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_ping_target m
|
||||||
|
ping_with m, Net::Ping::External
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_ping_http m
|
||||||
|
ping_with m, Net::Ping::HTTP
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_poke m
|
||||||
|
nick = BotpopBuiltins.get_ip_from_nick(m)[:nick]
|
||||||
|
ip = BotpopBuiltins.get_ip_from_nick(m)[:ip]
|
||||||
return m.reply "User '#{nick}' doesn't exists" if ip.nil?
|
return m.reply "User '#{nick}' doesn't exists" if ip.nil?
|
||||||
return m.reply "Cannot reach the host '#{ip}'" if not Botpop::Builtins.ping(ip)
|
|
||||||
s = dos_ip(ip)
|
|
||||||
r = Botpop::Builtins.ping(ip) ? "failed :(" : "down !!!"
|
|
||||||
m.reply "#{nick} : #{r} #{s}"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def trace_display_lines m, lines
|
|
||||||
lines.select!{|e| not e.include? "no reply" and e =~ /\A \d+: .+/}
|
|
||||||
duration = TRACE_DURATION_INIT
|
|
||||||
lines.each do |l|
|
|
||||||
m.reply l
|
|
||||||
sleep duration
|
|
||||||
duration += TRACE_DURATION_INCR
|
|
||||||
end
|
|
||||||
m.reply 'finished'
|
|
||||||
end
|
|
||||||
|
|
||||||
def trace_with_time ip
|
|
||||||
t1 = Time.now
|
|
||||||
s = Botpop::Builtins.trace ip
|
|
||||||
t2 = Time.now
|
|
||||||
return [s, t1, t2]
|
|
||||||
end
|
|
||||||
|
|
||||||
# see {trace_execution}. Seem system without sleep
|
|
||||||
#
|
|
||||||
# @arg lambda [Lambda] lambda with one argument (m). It wil be executed
|
|
||||||
def trace_execution(m, lambda)
|
|
||||||
@trace ||= Mutex.new
|
|
||||||
if @trace.try_lock
|
|
||||||
lambda.call(m) rescue nil
|
|
||||||
@trace.unlock
|
|
||||||
else
|
|
||||||
m.reply "A trace is still running"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_trace m
|
|
||||||
trace_execution m, lambda {|m|
|
|
||||||
ip = Botpop::Builtins.get_ip m
|
|
||||||
m.reply "It can take time"
|
|
||||||
begin
|
|
||||||
# Calculations
|
|
||||||
s, t1, t2 = trace_with_time ip
|
|
||||||
m.reply "Trace executed in #{(t2 - t1).round(3)} seconds"
|
|
||||||
rescue => e
|
|
||||||
m.reply "Sorry, but the last author of this plugin is so stupid his mother is a tomato"
|
|
||||||
end
|
|
||||||
# Display
|
# Display
|
||||||
trace_display_lines m, s
|
response = BotpopBuiltins.ping(ip) ? "#{(p.duration*100.0).round 2}ms (#{p.host})" : "failed"
|
||||||
}
|
m.reply "#{nick} > poke > #{response}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def self.dos_check_ip(m, ip)
|
||||||
|
return true if BotpopBuiltins.ping(ip)
|
||||||
|
m.reply "Cannot reach the host '#{ip}'"
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.dos_replier m, ip, s
|
||||||
|
if s.nil?
|
||||||
|
m.reply "The dos has failed"
|
||||||
|
elsif BotpopBuiltins.ping(ip)
|
||||||
|
m.reply "Sorry, the target is still up !"
|
||||||
|
else
|
||||||
|
m.reply "Target down ! --- #{s}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# This function avoid overusage of the resources by using mutex locking.
|
||||||
|
# It execute the lamdba function passed as 2sd parameter if resources are ok
|
||||||
|
# At the end of the attack, it wait few seconds (configuration) before
|
||||||
|
# releasing the resources and permit a new attack.
|
||||||
|
#
|
||||||
|
# @arg lambda [Lambda] lambda with one argument (m). It wil be executed
|
||||||
|
def self.dos_execution(m, lambda)
|
||||||
|
@dos ||= Mutex.new
|
||||||
|
if @dos.try_lock
|
||||||
|
lambda.call(m)
|
||||||
|
sleep DOS_WAIT_DURATION
|
||||||
|
@dos.unlock
|
||||||
|
else
|
||||||
|
m.reply "Wait for the end of the last dos"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.dos_ip(ip)
|
||||||
|
return BotpopBuiltins.dos(ip, DOS_DURATION).split("\n")[3].to_s rescue nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_dos m
|
||||||
|
dos_execution m, lambda {|m|
|
||||||
|
ip = BotpopBuiltins.get_ip m
|
||||||
|
return if not dos_check_ip(m, ip)
|
||||||
|
m.reply "Begin attack against #{ip}"
|
||||||
|
s = dos_ip(ip)
|
||||||
|
dos_replier m, ip, s
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_fok m
|
||||||
|
dos_execution m, lambda {|m|
|
||||||
|
nick = BotpopBuiltins.get_ip_from_nick(m)[:nick]
|
||||||
|
ip = BotpopBuiltins.get_ip_from_nick(m)[:ip]
|
||||||
|
return m.reply "User '#{nick}' doesn't exists" if ip.nil?
|
||||||
|
return m.reply "Cannot reach the host '#{ip}'" if not BotpopBuiltins.ping(ip)
|
||||||
|
s = dos_ip(ip)
|
||||||
|
r = BotpopBuiltins.ping(ip) ? "failed :(" : "down !!!"
|
||||||
|
m.reply "#{nick} : #{r} #{s}"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.trace_display_lines m, lines
|
||||||
|
lines.select!{|e| not e.include? "no reply" and e =~ /\A \d+: .+/}
|
||||||
|
duration = TRACE_DURATION_INIT
|
||||||
|
lines.each do |l|
|
||||||
|
m.reply l
|
||||||
|
sleep duration
|
||||||
|
duration += TRACE_DURATION_INCR
|
||||||
|
end
|
||||||
|
m.reply 'finished'
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.trace_with_time ip
|
||||||
|
t1 = Time.now
|
||||||
|
s = BotpopBuiltins.trace ip
|
||||||
|
t2 = Time.now
|
||||||
|
return [s, t1, t2]
|
||||||
|
end
|
||||||
|
|
||||||
|
# see {trace_execution}. Seem system without sleep
|
||||||
|
#
|
||||||
|
# @arg lambda [Lambda] lambda with one argument (m). It wil be executed
|
||||||
|
def self.trace_execution(m, lambda)
|
||||||
|
@trace ||= Mutex.new
|
||||||
|
if @trace.try_lock
|
||||||
|
lambda.call(m) rescue nil
|
||||||
|
@trace.unlock
|
||||||
|
else
|
||||||
|
m.reply "A trace is still running"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_trace m
|
||||||
|
trace_execution m, lambda {|m|
|
||||||
|
ip = BotpopBuiltins.get_ip m
|
||||||
|
m.reply "It can take time"
|
||||||
|
begin
|
||||||
|
# Calculations
|
||||||
|
s, t1, t2 = trace_with_time ip
|
||||||
|
m.reply "Trace executed in #{(t2 - t1).round(3)} seconds"
|
||||||
|
rescue => e
|
||||||
|
m.reply "Sorry, but the last author of this plugin is so stupid his mother is a tomato"
|
||||||
|
end
|
||||||
|
# Display
|
||||||
|
trace_display_lines m, s
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
#encoding: utf-8
|
|
||||||
|
|
||||||
class Ops < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/!op/, use_prefix: false, method: :exec_op)
|
|
||||||
match(/!op (.+)/, use_prefix: false, method: :exec_op_other)
|
|
||||||
match(/!deop/, use_prefix: false, method: :exec_deop)
|
|
||||||
match(/!deop (.+)/, use_prefix: false, method: :exec_deop_other)
|
|
||||||
match(/!v/, use_prefix: false, method: :exec_voice)
|
|
||||||
match(/!v (.+)/, use_prefix: false, method: :exec_voice_other)
|
|
||||||
match(/!dv/, use_prefix: false, method: :exec_devoice)
|
|
||||||
match(/!dv (.+)/, use_prefix: false, method: :exec_devoice_other)
|
|
||||||
|
|
||||||
HELP = ["!op <nickname>", "!deop <nickname>"]
|
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def exec_op m
|
|
||||||
m.channel.op(m.user)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_op_other m, other
|
|
||||||
m.channel.op(other)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_deop m
|
|
||||||
m.channel.deop(m.user)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_deop_other m, other
|
|
||||||
m.channel.deop(other)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_voice m
|
|
||||||
m.channel.voice(m.user)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_voice_other m, other
|
|
||||||
m.channel.voice(other)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_devoice m
|
|
||||||
m.channel.devoice(m.user)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_devoice_other m, other
|
|
||||||
m.channel.devoice(other)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,17 +0,0 @@
|
||||||
# coding: utf-8
|
|
||||||
|
|
||||||
class Poilo < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/^[^!].+/, use_prefix: false, method: :exec_poilo)
|
|
||||||
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
SYLLABE = %w(a i o u y oi eau au ou an eu)
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def exec_poilo m
|
|
||||||
word = m.message.split.last
|
|
||||||
syl = word.split(/[^aeiouy]/).last
|
|
||||||
m.reply "poil au " + CONFIG["list"][syl] if not syl.nil?
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,76 +0,0 @@
|
||||||
#encoding: utf-8
|
|
||||||
|
|
||||||
class Points < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
include Botpop::Plugin::Database
|
|
||||||
|
|
||||||
match(/.*/, use_prefix: false, method: :save_last_user)
|
|
||||||
match(/^!pstats?$/, use_prefix: false, method: :statistics)
|
|
||||||
match(/^!pstats?u (\w+)$/, use_prefix: false, method: :statistics_for_user)
|
|
||||||
match(/^!pstats?p (\w+)$/, use_prefix: false, method: :statistics_for_point)
|
|
||||||
match(/^!p +(\w+)$/, use_prefix: false, method: :add_point_to_last)
|
|
||||||
match(/^!p +(\w+) +(\w+)$/, use_prefix: false, method: :add_point_to_user)
|
|
||||||
match(/hei(l|i)/i, use_prefix: false, method: :point_nazi)
|
|
||||||
|
|
||||||
HELP = ["!p <type> [to]", "!pstats", "!pstatsu <nick>", "!pstatsp <point>"]
|
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
@@users = {}
|
|
||||||
@@lock = Mutex.new
|
|
||||||
|
|
||||||
def statistics m
|
|
||||||
ret = Base::DB.fetch("SELECT points.type, COUNT(*) AS nb FROM points GROUP BY points.type ORDER BY nb DESC LIMIT 10;").all.map{|e| e[:type] + "(#{e[:nb]})"}.join(", ")
|
|
||||||
# data = Base::DB.fetch("SELECT points.type, COUNT(points.*) AS nb FROM points GROUP BY points.type ORDER BY nb DESC LIMIT 10;").all
|
|
||||||
# data.map!{|e| Base::DB.fetch("SELECT assigned_to FROM points GROUP BY type, assigned_to HAVING type = ? ORDER BY COUNT(*) DESC;", e[:type]).first.merge(e)}
|
|
||||||
# ret = data.map{|e| e[:type] + "(#{e[:nb]}x #{e[:assigned_to]})"}.join(", ")
|
|
||||||
m.reply "Top used: #{ret}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def statistics_for_user m, u
|
|
||||||
ret = Base::DB.fetch("SELECT points.type, COUNT(*) AS nb FROM points WHERE assigned_to = ? GROUP BY points.type ORDER BY COUNT(*) DESC LIMIT 10;", u.downcase).all.map{|e| e[:type] + "(#{e[:nb]})"}.join(", ")
|
|
||||||
m.reply "User #{u} has: #{ret}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def statistics_for_point m, p
|
|
||||||
data = Base::DB.fetch("SELECT assigned_to, COUNT(*) AS nb FROM points GROUP BY type, assigned_to HAVING type = ? ORDER BY COUNT(*) DESC LIMIT 10;", p).all
|
|
||||||
ret = data.map{|e| e[:assigned_to] + "(#{e[:nb]})"}.join(", ")
|
|
||||||
m.reply "Point #{p}: #{ret}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def save_last_user m
|
|
||||||
return if m.message.match(/^!p .+$/)
|
|
||||||
@@lock.lock
|
|
||||||
@@users[m.channel.to_s] = m.user.nick
|
|
||||||
@@lock.unlock
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_point_to_last m, type
|
|
||||||
return if @@users[m.channel.to_s].nil?
|
|
||||||
nick = @@users[m.channel.to_s]
|
|
||||||
count = add_point(m.user.nick, nick, type)
|
|
||||||
m.reply "#{nick} has now #{count} points #{type} !"
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_point_to_user m, type, nick
|
|
||||||
count = add_point(m.user.nick, nick, type)
|
|
||||||
m.reply "#{nick} has now #{count} points #{type} !"
|
|
||||||
end
|
|
||||||
|
|
||||||
def point_nazi m
|
|
||||||
nick = m.user.nick
|
|
||||||
count = add_point("self", nick, "nazi")
|
|
||||||
m.reply "#{nick} has now #{count} points nazi !" if count % 10 == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def add_point(by, to, type)
|
|
||||||
to.downcase!
|
|
||||||
Base::DB[:points].insert({assigned_by: by,
|
|
||||||
assigned_to: to,
|
|
||||||
type: type,
|
|
||||||
created_at: Time.now})
|
|
||||||
Base::DB[:points].where(assigned_to: to, type: type).count
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,12 +0,0 @@
|
||||||
require 'sequel'
|
|
||||||
|
|
||||||
class Point < Sequel::Model
|
|
||||||
|
|
||||||
def before_save
|
|
||||||
return false if super == false
|
|
||||||
self.created_at = Time.now
|
|
||||||
end
|
|
||||||
|
|
||||||
set_dataset Base::DB[:points]
|
|
||||||
|
|
||||||
end
|
|
|
@ -1 +0,0 @@
|
||||||
base/migrations/
|
|
214
plugins/proxy.rb
214
plugins/proxy.rb
|
@ -1,123 +1,127 @@
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
trap('SIGINT') {
|
trap('SIGINT') {
|
||||||
Botpop::Plugins::Proxy.database_users_write({})
|
BotpopPlugins::Proxy.database_users_write({})
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
class Proxy < Botpop::Plugin
|
module BotpopPlugins
|
||||||
include Cinch::Plugin
|
module Proxy
|
||||||
|
|
||||||
match("!proxy list", use_prefix: false, method: :exec_proxy_list)
|
MATCH = lambda do |parent, plugin|
|
||||||
match("!proxy ip", use_prefix: false, method: :exec_proxy_ip)
|
parent.on :message, "!proxy list" do |m| plugin.exec_proxy_list m end
|
||||||
match("!proxy get", use_prefix: false, method: :exec_proxy_get)
|
parent.on :message, "!proxy ip" do |m| plugin.exec_proxy_ip m end
|
||||||
match("!proxy drop", use_prefix: false, method: :exec_proxy_drop)
|
parent.on :message, "!proxy get" do |m| plugin.exec_proxy_get m end
|
||||||
|
parent.on :message, "!proxy drop" do |m| plugin.exec_proxy_drop m end
|
||||||
HELP = ["!proxy list", "!proxy ip", "!proxy get", "!proxy drop"]
|
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
|
||||||
|
|
||||||
if ENABLED
|
|
||||||
require 'htauth'
|
|
||||||
require 'digest'
|
|
||||||
end
|
|
||||||
|
|
||||||
LIMIT_USERS = config['limit_users'] || 1
|
|
||||||
PASSWD_FILE = config['passwd_file'] || '/etc/squid3/passwords'
|
|
||||||
IP = config['ip_addr'] || raise(MissingConfigurationEntry, 'ip_addr')
|
|
||||||
PORT = config['ip_port'] || raise(MissingConfigurationEntry, 'ip_port')
|
|
||||||
|
|
||||||
File.open(PASSWD_FILE, 'a') {}
|
|
||||||
LOCKED_USERS = File.readlines(PASSWD_FILE)
|
|
||||||
|
|
||||||
@@proxy_users = []
|
|
||||||
|
|
||||||
def username m
|
|
||||||
Digest::SHA256.hexdigest m.user.nick
|
|
||||||
end
|
|
||||||
|
|
||||||
def password_rand
|
|
||||||
File.readlines('/proc/sys/kernel/random/uuid').first.split('-').last.chomp
|
|
||||||
end
|
|
||||||
|
|
||||||
def database_users_reset
|
|
||||||
File.write(PASSWD_FILE, '')
|
|
||||||
end
|
|
||||||
|
|
||||||
def database_users_read
|
|
||||||
begin
|
|
||||||
return File.readlines(PASSWD_FILE)
|
|
||||||
rescue
|
|
||||||
database_users_reset
|
|
||||||
sleep 1
|
|
||||||
retry
|
|
||||||
end
|
end
|
||||||
end
|
HELP = ["!proxy list", "!proxy ip",
|
||||||
|
"!proxy get", "!proxy drop"]
|
||||||
|
CONFIG = Botpop::CONFIG['proxy'] || raise(MissingConfigurationZone, 'proxy')
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
|
|
||||||
def database_users_write users
|
if ENABLED
|
||||||
database_users_reset
|
require 'htauth'
|
||||||
contents = (LOCKED_USERS + users.map{|u,p| "#{u}:#{p}"}).join("\n").chomp
|
require 'digest'
|
||||||
contents += "\n" if not contents.empty?
|
|
||||||
File.write(PASSWD_FILE, contents)
|
|
||||||
end
|
|
||||||
|
|
||||||
def users
|
|
||||||
users = database_users_read
|
|
||||||
users.map!{|l| l.chomp.split(':')}
|
|
||||||
users.map!{|u| {u[0] => u[1]}}
|
|
||||||
users = users.reduce({}) {|h,pairs| pairs.each {|k,v| h[k] = v}; h}
|
|
||||||
users
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_user nick
|
|
||||||
users = database_users_read
|
|
||||||
users.delete_if {|line| line =~ /\A#{nick}:.+/ }
|
|
||||||
database_users_write users
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_user username, password
|
|
||||||
p = HTAuth::PasswdFile.new(PASSWD_FILE)
|
|
||||||
p.add(username, password)
|
|
||||||
p.save!
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_exists? m
|
|
||||||
users[username m]
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_proxy_list m
|
|
||||||
users.keys.each_with_index do |username, i|
|
|
||||||
m.reply "Proxy list [#{i+1}/#{users.size}/#{LIMIT_USERS}] : #{username}"
|
|
||||||
sleep 0.1
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def exec_proxy_ip m
|
LIMIT_USERS = CONFIG['limit_users'] || 1
|
||||||
m.reply "Proxy connexion on http://#{IP}:#{PORT}"
|
PASSWD_FILE = CONFIG['passwd_file'] || '/etc/squid3/passwords'
|
||||||
end
|
IP = CONFIG['ip_addr'] || raise(MissingConfigurationEntry, 'ip_addr')
|
||||||
|
PORT = CONFIG['ip_port'] || raise(MissingConfigurationEntry, 'ip_port')
|
||||||
|
|
||||||
def exec_proxy_get m
|
File.open(PASSWD_FILE, 'a') {}
|
||||||
if not user_exists? m
|
LOCKED_USERS = File.readlines(PASSWD_FILE)
|
||||||
password = password_rand
|
|
||||||
@@proxy_users << m.user.nick
|
@@proxy_users = []
|
||||||
add_user(username(m), password)
|
|
||||||
m.reply "User : #{username(m)} created, password : #{password}"
|
def self.username m
|
||||||
else
|
Digest::SHA256.hexdigest m.user.nick
|
||||||
if @@proxy_users.include? m.user.nick
|
end
|
||||||
m.reply "You already have a proxy. Drop it before creating a new one."
|
|
||||||
else
|
def self.password_rand
|
||||||
m.reply "Locked nick #{m.user.nick} out of the my jurisdiction. Use an other."
|
File.readlines('/proc/sys/kernel/random/uuid').first.split('-').last.chomp
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.database_users_reset
|
||||||
|
File.write(PASSWD_FILE, '')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.database_users_read
|
||||||
|
begin
|
||||||
|
return File.readlines(PASSWD_FILE)
|
||||||
|
rescue
|
||||||
|
database_users_reset
|
||||||
|
sleep 1
|
||||||
|
retry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def exec_proxy_drop m
|
def self.database_users_write users
|
||||||
if @@proxy_users.include?(m.user.nick) and user_exists? m
|
database_users_reset
|
||||||
@@proxy_users.delete(m.user.nick)
|
contents = (LOCKED_USERS + users.map{|u,p| "#{u}:#{p}"}).join("\n").chomp
|
||||||
remove_user(username(m))
|
contents += "\n" if not contents.empty?
|
||||||
m.reply "Removed."
|
File.write(PASSWD_FILE, contents)
|
||||||
else
|
|
||||||
m.reply "No proxy registered with your nick on my jurisdiction."
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
def self.users
|
||||||
|
users = database_users_read
|
||||||
|
users.map!{|l| l.chomp.split(':')}
|
||||||
|
users.map!{|u| {u[0] => u[1]}}
|
||||||
|
users = users.reduce({}) {|h,pairs| pairs.each {|k,v| h[k] = v}; h}
|
||||||
|
users
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.remove_user nick
|
||||||
|
users = database_users_read
|
||||||
|
users.delete_if {|line| line =~ /\A#{nick}:.+/ }
|
||||||
|
database_users_write users
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.add_user username, password
|
||||||
|
p = HTAuth::PasswdFile.new(PASSWD_FILE)
|
||||||
|
p.add(username, password)
|
||||||
|
p.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.user_exists? m
|
||||||
|
users[username m]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_proxy_list m
|
||||||
|
users.keys.each_with_index do |username, i|
|
||||||
|
m.reply "Proxy list [#{i+1}/#{users.size}/#{LIMIT_USERS}] : #{username}"
|
||||||
|
sleep 0.1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_proxy_ip m
|
||||||
|
m.reply "Proxy connexion on http://#{IP}:#{PORT}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_proxy_get m
|
||||||
|
if not user_exists? m
|
||||||
|
password = password_rand
|
||||||
|
@@proxy_users << m.user.nick
|
||||||
|
add_user(username(m), password)
|
||||||
|
m.reply "User : #{username(m)} created, password : #{password}"
|
||||||
|
else
|
||||||
|
if @@proxy_users.include? m.user.nick
|
||||||
|
m.reply "You already have a proxy. Drop it before creating a new one."
|
||||||
|
else
|
||||||
|
m.reply "Locked nick #{m.user.nick} out of the my jurisdiction. Use an other."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exec_proxy_drop m
|
||||||
|
if @@proxy_users.include?(m.user.nick) and user_exists? m
|
||||||
|
@@proxy_users.delete(m.user.nick)
|
||||||
|
remove_user(username(m))
|
||||||
|
m.reply "Removed."
|
||||||
|
else
|
||||||
|
m.reply "No proxy registered with your nick on my jurisdiction."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
require 'date'
|
|
||||||
|
|
||||||
class Puppet < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/^!pm (\#*\w+) (.*)/, use_prefix: false, method: :send_privmsg)
|
|
||||||
match(/^!join (\#\w+)/, use_prefix: false, method: :join)
|
|
||||||
match(/^!part (\#\w+)/, use_prefix: false, method: :part)
|
|
||||||
|
|
||||||
# Email handlement
|
|
||||||
EMAIL = '[[:alnum:]\.\-_]{1,64}@[[:alnum:]\.\-_]{1,64}'
|
|
||||||
NICK = '\w+'
|
|
||||||
# Registration of an email address - association with authname
|
|
||||||
match(/^!mail register (#{EMAIL})$/, use_prefix: false, method: :register)
|
|
||||||
match(/^!mail primary (#{EMAIL})$/, use_prefix: false, method: :make_primary)
|
|
||||||
# Send email to user through its nickname (not safe)
|
|
||||||
match(/^!(mail )?(let|send) (#{NICK}) (.+)/, use_prefix: false, method: :let)
|
|
||||||
# Send email to user through one of its emails (safe)
|
|
||||||
match(/^!(mail )?(let|send) (#{EMAIL}) (.+)/, use_prefix: false, method: :let)
|
|
||||||
# Read email (based on nickname, authname, and emails)
|
|
||||||
match(/^!(mail )?r(ead)?$/, use_prefix: false, method: :read)
|
|
||||||
|
|
||||||
HELP = ["!pm <#chat/nick> <message>", "!join <#chan>", "!part <#chan>", "!let <to> msg", "!read"] +
|
|
||||||
["!mail read", "!mail send/let <...>", "!mail register address"]
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def send_privmsg m, what, message
|
|
||||||
if what.match(/^\#.+/)
|
|
||||||
send_privmsg_to_channel(what, message)
|
|
||||||
else
|
|
||||||
send_privmsg_to_user(what, message)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def join m, chan
|
|
||||||
Channel(chan).join
|
|
||||||
end
|
|
||||||
|
|
||||||
def part m, chan
|
|
||||||
Channel(chan).part
|
|
||||||
end
|
|
||||||
|
|
||||||
def register m, email
|
|
||||||
begin
|
|
||||||
Base::DB[:emails].insert(authname: m.user.authname,
|
|
||||||
address: email,
|
|
||||||
created_at: Time.now.utc,
|
|
||||||
usage: 0)
|
|
||||||
rescue => _
|
|
||||||
return m.reply "Error, cannot register this email !"
|
|
||||||
end
|
|
||||||
return m.reply "Email #{email} registered for you, #{m.user.authname}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def make_primary m, email
|
|
||||||
a = get_addresses(m.user).where(address: email)
|
|
||||||
return m.reply "No your email #{email}" if a.first.nil?
|
|
||||||
get_addresses(m.user).update(primary: false)
|
|
||||||
a.update(primary: true)
|
|
||||||
m.reply "Your primary email #{m.user.nick} is now #{email}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def let m, _, _, to, msg
|
|
||||||
log "New message addressed to #{to} to send"
|
|
||||||
# insert new message in database
|
|
||||||
from = Base::DB[:emails].where(authname: m.user.authname, primary: true).select(:address).first
|
|
||||||
from = from && from[:address] || m.user.nick
|
|
||||||
Base::DB[:messages].insert(author: from,
|
|
||||||
dest: to,
|
|
||||||
content: msg.strip,
|
|
||||||
created_at: Time.now,
|
|
||||||
read_at: nil)
|
|
||||||
Base::DB[:emails].where(address: to).update('usage = usage+1')
|
|
||||||
end
|
|
||||||
|
|
||||||
def read m, _
|
|
||||||
msg = get_messages(m.user).first
|
|
||||||
if msg.nil?
|
|
||||||
send_privmsg_to_user m.user, "No message."
|
|
||||||
return
|
|
||||||
end
|
|
||||||
Base::DB[:messages].where(id: msg[:id]).update(read_at: Time.now)
|
|
||||||
date = msg[:created_at]
|
|
||||||
if Date.parse(Time.now.to_s) == Date.parse(date.to_s)
|
|
||||||
date = date.strftime("%H:%M:%S")
|
|
||||||
else
|
|
||||||
date = date.strftime("%B, %d at %H:%M:%S")
|
|
||||||
end
|
|
||||||
send_privmsg_to_user m.user, "##{msg[:id]}# #{date} -- from #{msg[:author]}"
|
|
||||||
send_privmsg_to_user m.user, msg[:content]
|
|
||||||
end
|
|
||||||
|
|
||||||
listen_to :join, method: :bip_on_join
|
|
||||||
|
|
||||||
def bip_on_join m
|
|
||||||
nb = Base::DB[:messages].where(dest: m.user.nick, read_at: nil).count
|
|
||||||
send_privmsg_to_user m.user, "#{m.user.nick}: You have #{nb} message unread." unless nb.zero?
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def send_privmsg_to_channel chan, msg
|
|
||||||
Channel(chan).send(msg.strip)
|
|
||||||
end
|
|
||||||
|
|
||||||
def send_privmsg_to_user user, msg
|
|
||||||
User(user).send(msg.strip)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_messages user
|
|
||||||
emails = Base::DB[:emails].where(authname: user.authname).select(:address).all.map(&:values).flatten
|
|
||||||
Base::DB[:messages].where(dest: [user.nick, user.authname] + emails).where(read_at: nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_addresses user
|
|
||||||
Base::DB[:emails].where(authname: user.authname)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,42 +0,0 @@
|
||||||
require "base64"
|
|
||||||
|
|
||||||
class RootMe < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
FloatRegexp = "\d+(\.\d+)?"
|
|
||||||
match(/!ep1 (\w+)/, use_prefix: false, method: :start_ep1)
|
|
||||||
match(/!ep2 (\w+)/, use_prefix: false, method: :start_ep2)
|
|
||||||
match(/^(#{FloatRegexp}) ?\/ ?(#{FloatRegexp})$/, use_prefix: false, method: :play_ep1)
|
|
||||||
match(/^(\d+) ?\/ ?(\d+)$/, use_prefix: false, method: :play_ep1)
|
|
||||||
match(/^(\w+)$/, use_prefix: false, method: :play_ep2)
|
|
||||||
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
def start_ep1 m, botname
|
|
||||||
bot = User(botname)
|
|
||||||
bot.send "!ep1"
|
|
||||||
end
|
|
||||||
|
|
||||||
def start_ep2 m, botname
|
|
||||||
bot = User(botname)
|
|
||||||
bot.send "!ep2"
|
|
||||||
end
|
|
||||||
|
|
||||||
def play_ep1 m, n1, n2
|
|
||||||
r = n1.to_f**(0.5) * n2.to_f
|
|
||||||
str = "!ep1 -rep #{r.round 2}"
|
|
||||||
puts str
|
|
||||||
m.reply str
|
|
||||||
# response will be logged by the bot, check the log
|
|
||||||
end
|
|
||||||
|
|
||||||
def play_ep2 m, b64
|
|
||||||
r = Base64.decode64(b64)
|
|
||||||
str = "!ep2 -rep #{r}"
|
|
||||||
puts str
|
|
||||||
m.reply str
|
|
||||||
# response will be logged by the bot, check the log
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,16 +1,20 @@
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
class SayGoodBye < Botpop::Plugin
|
module BotpopPlugins
|
||||||
include Cinch::Plugin
|
module SayGoodByePlugin
|
||||||
|
NAME = self.to_s.split(':').last
|
||||||
|
|
||||||
match(/^!sg [\w\-\.].+/, use_prefix: false, method: :exec_sg)
|
MATCH = lambda do |parent, plugin|
|
||||||
|
parent.on :message, /!sg [\w\d_\-\.].+/ do |m| plugin.exec_sg m end
|
||||||
|
end
|
||||||
|
HELP = ["!sg src_name"]
|
||||||
|
CONFIG = Botpop::CONFIG['say_goodbye'] || raise(MissingConfigurationZone, NAME)
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
|
|
||||||
HELP = ["!sg src_name"]
|
def self.exec_sg m
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
arg = m.message.split.last
|
||||||
|
m.reply CONFIG[arg].shuffle.first
|
||||||
|
end
|
||||||
|
|
||||||
def exec_sg m
|
|
||||||
arg = m.message.split.last
|
|
||||||
m.reply config[arg].sample
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
class Searchable < Botpop::Plugin
|
module BotpopPlugins
|
||||||
include Cinch::Plugin
|
module Searchable
|
||||||
|
|
||||||
ENABLED = config['enable'].nil? ? true : config['enable']
|
MATCH = lambda do |parent, plugin|
|
||||||
|
parent.on :message, /\!(#{CONFIG.keys.join('|')}) .+/ do |m| plugin.exec_search m end
|
||||||
|
end
|
||||||
|
CONFIG = Botpop::CONFIG['searchable'] || raise(MissingConfigurationZone, 'base')
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
||||||
|
|
||||||
VALUES = config.values.map{|e|"!"+e}.join(', ')
|
VALUES = CONFIG.values.map{|e|"!"+e}.join(', ')
|
||||||
KEYS = config.keys.map{|e|"!"+e}.join(', ')
|
KEYS = CONFIG.keys.map{|e|"!"+e}.join(', ')
|
||||||
HELP = config.keys.map{|e|"!"+e+" [search]"}
|
HELP = CONFIG.keys.map{|e|"!"+e+" [search]"}
|
||||||
CONFIG = config
|
|
||||||
match(/\!(#{config.keys.join('|')}) .+/, use_prefix: false, method: :exec_search)
|
def self.exec_search m
|
||||||
|
msg = BotpopBuiltins.get_msg m
|
||||||
|
url = CONFIG[m.params[1..-1].join(' ').gsub(/\!([^ ]+) .+/, '\1')]
|
||||||
|
url = url.gsub('___MSG___', msg)
|
||||||
|
m.reply url
|
||||||
|
end
|
||||||
|
|
||||||
def exec_search m
|
|
||||||
msg = Botpop::Builtins.get_msg m
|
|
||||||
url = CONFIG[m.params[1..-1].join(' ').gsub(/\!([^ ]+) .+/, '\1')]
|
|
||||||
url = url.gsub('___MSG___', msg)
|
|
||||||
m.reply url
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,32 +1,31 @@
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
class Taggle < Botpop::Plugin
|
module BotpopPlugins
|
||||||
include Cinch::Plugin
|
module Taggle
|
||||||
|
NAME = self.to_s.split(':').last
|
||||||
|
|
||||||
match(/!tg (.+)/, use_prefix: false, method: :exec_tg)
|
MATCH = lambda do |parent, plugin|
|
||||||
|
# Self is the callback, containing User()
|
||||||
HELP = ["!tg [nick]"]
|
parent.on :message, /!tg (.+)/ do |m, who| plugin.exec_tg self, m, who end
|
||||||
CONFIG = config(safe: true) || {}
|
|
||||||
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
|
|
||||||
NTIMES = CONFIG['ntimes'] || 10
|
|
||||||
WAIT = CONFIG['wait'] || 0.3
|
|
||||||
|
|
||||||
def cmd_allowed? m
|
|
||||||
return Base.cmd_allowed? m, ["tg"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_tg m, who
|
|
||||||
return if not cmd_allowed? m
|
|
||||||
@@tg_lock ||= Mutex.new
|
|
||||||
@@tg_lock.lock
|
|
||||||
begin
|
|
||||||
NTIMES.times do
|
|
||||||
User(who).send("tg #{who}")
|
|
||||||
sleep WAIT
|
|
||||||
end
|
|
||||||
ensure
|
|
||||||
@@tg_lock.unlock
|
|
||||||
end
|
end
|
||||||
end
|
HELP = ["!tg [nick]"]
|
||||||
|
CONFIG = Botpop::CONFIG['taggle'] || {} # || raise(MissingConfigurationZone, NAME)
|
||||||
|
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable'] rescue true
|
||||||
|
NTIMES = CONFIG['ntimes'] || 10
|
||||||
|
WAIT = CONFIG['wait'] || 0.3
|
||||||
|
|
||||||
|
def self.exec_tg c, m, who
|
||||||
|
@tg_lock ||= Mutex.new
|
||||||
|
@tg_lock.lock
|
||||||
|
begin
|
||||||
|
NTIMES.times do
|
||||||
|
c.User(who).send("tg #{who}")
|
||||||
|
sleep WAIT
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
@tg_lock.unlock
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
require 'mechanize'
|
|
||||||
|
|
||||||
class Youtube < Botpop::Plugin
|
|
||||||
include Cinch::Plugin
|
|
||||||
|
|
||||||
match(/!yt (.+)/, use_prefix: false, method: :find_youtube_video)
|
|
||||||
|
|
||||||
HELP = ["!yt title"]
|
|
||||||
ENABLED = config['enable'].nil? ? false : config['enable']
|
|
||||||
CONFIG = config
|
|
||||||
|
|
||||||
private
|
|
||||||
def search_url(title)
|
|
||||||
CONFIG['search_url'].gsub('___MSG___', title)
|
|
||||||
end
|
|
||||||
def reduce_url(url)
|
|
||||||
CONFIG['reduce_url'].gsub('___ID___', url.gsub(/^(.+)(v=)(\w+)$/, '\3'))
|
|
||||||
end
|
|
||||||
def display(result)
|
|
||||||
CONFIG['display']
|
|
||||||
.gsub('___TITLE___', result[:title])
|
|
||||||
.gsub('___URL___', reduce_url(result[:url]))
|
|
||||||
end
|
|
||||||
public
|
|
||||||
|
|
||||||
def find_youtube_video m, title
|
|
||||||
e = Mechanize.new
|
|
||||||
e.get(search_url(title))
|
|
||||||
result = {
|
|
||||||
title: e.page.at(".item-section li").at('h3').text,
|
|
||||||
url: e.page.at(".item-section li").at('a')[:href],
|
|
||||||
}
|
|
||||||
m.reply display(result)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -17,8 +17,8 @@ class TestBotbot < Test::Unit::TestCase
|
||||||
assert(Botpop::CONFIG)
|
assert(Botpop::CONFIG)
|
||||||
assert(Botpop::TARGET)
|
assert(Botpop::TARGET)
|
||||||
assert(Botpop::PluginInclusion.class == Module)
|
assert(Botpop::PluginInclusion.class == Module)
|
||||||
assert(Botpop::Builtins.class == Module)
|
assert(BotpopBuiltins.class == Module)
|
||||||
assert(Botpop::Plugin.class == Class)
|
assert(BotpopPlugins.class == Module)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user