├── .travis.yml ├── spec ├── spec_helper.cr └── bycharabot_spec.cr ├── .gitignore ├── shard.lock ├── .editorconfig ├── config.template.yml ├── shard.yml ├── text.txt ├── LICENSE ├── README.md └── src └── bycharabot.cr /.travis.yml: -------------------------------------------------------------------------------- 1 | language: crystal 2 | -------------------------------------------------------------------------------- /spec/spec_helper.cr: -------------------------------------------------------------------------------- 1 | require "spec" 2 | require "../src/bycharabot" 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /docs/ 2 | /lib/ 3 | /bin/ 4 | /.shards/ 5 | *.dwarf 6 | /dev/ 7 | /sentry 8 | /config.yml -------------------------------------------------------------------------------- /shard.lock: -------------------------------------------------------------------------------- 1 | version: 1.0 2 | shards: 3 | fast_irc: 4 | github: RX14/fast_irc.cr 5 | version: 0.3.3 6 | 7 | -------------------------------------------------------------------------------- /spec/bycharabot_spec.cr: -------------------------------------------------------------------------------- 1 | require "./spec_helper" 2 | 3 | describe Bycharabot do 4 | # TODO: Write tests 5 | 6 | it "works" do 7 | false.should eq(true) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.cr] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 2 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /config.template.yml: -------------------------------------------------------------------------------- 1 | server: "localhost" 2 | port: 6667 3 | connection_timeout: 10 4 | vote_kick: 5 5 | nickname: "bycharabot" 6 | channels: ["general"] 7 | regex: ["[\\n,.!?;:()-]", "\\x03(\\d{1,2}(,\\d{1,2})?)?", "<\\s*\\w.*?>", "\\[\\s*\\w.*?\\]"] -------------------------------------------------------------------------------- /shard.yml: -------------------------------------------------------------------------------- 1 | name: bycharabot 2 | version: 0.1.0 3 | 4 | authors: 5 | - Ivan Kuzmenko 6 | 7 | targets: 8 | bycharabot: 9 | main: src/bycharabot.cr 10 | 11 | dependencies: 12 | fast_irc: 13 | github: RX14/fast_irc.cr 14 | version: 0.3.3 15 | 16 | crystal: 0.26.0 17 | 18 | license: MIT 19 | -------------------------------------------------------------------------------- /text.txt: -------------------------------------------------------------------------------- 1 | А я не Пушкин и не Круг 2 | Я - отморозок, бык и гад 3 | Я ненавижу белый свет 4 | И только водке, хуле, рад 5 | А я не Пушкин и не Круг 6 | Хотя я тоже не гандон 7 | Я не читаю сраных книг 8 | Я по ночам иду на взлом 9 | Я всех построю 10 | Я всех зарою 11 | Я - бык, бычара 12 | Бля, я быкую 13 | Я - бык, бычара 14 | Бык - отморозок 15 | Быкую, сука 16 | Пиздец быкую 17 | Да, я не Пушкин, хуле бля 18 | Я - отморозок, бля, пиздец 19 | Ежель ты мне не понравился 20 | Ты больше не жилец 21 | Мне до пизды, мне по хую 22 | Я, сука, всех приговорю 23 | Мне до пизды, мне по хую 24 | Я, сука, всех приговорю 25 | Я всех построю 26 | Я всех зарою 27 | Я - бык, бычара 28 | Бля, я быкую 29 | Я - бык, бычара 30 | Бык - отморозок 31 | Быкую, сука 32 | Пиздец быкую -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Ivan Kuzmenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bycharabot 2 | 3 | Бот для IRC, который может построить и зарыть. 4 | 5 | ## Installation 6 | 7 | TODO: Write installation instructions here 8 | 9 | ## Usage 10 | 11 | **Настройка:** 12 | 1. Переименуйте файл `config.template.yml` в `config.yml` 13 | 2. Измените по желанию переменные в `config.yml`. 14 | `server` - адрес сервера. 15 | `port` - порт сервера. 16 | `connection_timeout` - таймаут соединения в секундах. 17 | `vote_kick` - сколько нужно голосов, чтобы бот покинул канал. **На данный момент ничего не делает.** 18 | `nickname` - имя бота. 19 | `channels` - массив каналов, к которым бот автоматически подсоединится. **Писать канал нужно без решётки в начале!** 20 | `regex` - массив регулярных выражений для удаления ненужных символов из сообщения. **Формат: PCRE.** 21 | 22 | **Команды:** 23 | `любая строка из text.txt, кроме последней` - бот напишет следующую строку. 24 | `(а) кто такой *имя бота*` - бот ответит `Я - самый полезный бот. Кто не согласен, тот будет построен и зарыт.` 25 | `~inv #канал` - бот зайдёт на канал из первого аргумента. 26 | `~leave` - проголосовать за выход бота из сервера. **На данный момент ничего не делает.** 27 | 28 | ## Development 29 | 30 | TODO: Write development instructions here 31 | 32 | ## Contributing 33 | 34 | 1. Fork it () 35 | 2. Create your feature branch (`git checkout -b my-new-feature`) 36 | 3. Commit your changes (`git commit -am 'Add some feature'`) 37 | 4. Push to the branch (`git push origin my-new-feature`) 38 | 5. Create a new Pull Request 39 | 40 | ## Contributors 41 | 42 | - [iVAN2002](https://github.com/iVAN2002) Ivan Kuzmenko - creator, maintainer 43 | -------------------------------------------------------------------------------- /src/bycharabot.cr: -------------------------------------------------------------------------------- 1 | require "fast_irc" 2 | require "file" 3 | require "yaml" 4 | require "socket" 5 | require "regex" 6 | 7 | # TODO: Write documentation for `Bycharabot` 8 | class Bycharabot 9 | VERSION = "0.1.0" 10 | 11 | @server = "" 12 | @port = 6667 13 | @connection_timeout = 10 14 | @vote_kick = 5 15 | @nickname = "Bychara" 16 | @channels = [] of String 17 | @regex = [] of Regex 18 | 19 | @lines_normal = [] of String 20 | @lines_bot = [] of String 21 | @prev_line = {} of String => Int32 22 | @votekick_users = [] of String 23 | 24 | @client = TCPSocket.new 25 | 26 | @logged_in = false 27 | 28 | @used_times = 0 29 | 30 | def loadAndParse 31 | data = YAML::Any 32 | if (ENV.fetch("LAUNCH_ENV", "LOCAL") == "HEROKU") 33 | data = YAML.parse(ENV.fetch("BOT_SETTINGS", "")) 34 | else 35 | data = YAML.parse(File.read("./config.yml")) 36 | end 37 | @server = data["server"].to_s 38 | @port = data["port"].as_i 39 | @connection_timeout = data["connection_timeout"].as_i 40 | @vote_kick = data["vote_kick"].as_i 41 | @nickname = data["nickname"].to_s 42 | data["channels"].as_a.each do |el| 43 | @channels.push(el.to_s) 44 | @prev_line[el.to_s] = 0 45 | end 46 | 47 | data["regex"].as_a.each do |el| 48 | @regex.push(Regex.new(el.to_s)) 49 | end 50 | 51 | @lines_normal = File.read_lines("text.txt") 52 | 53 | @lines_normal.each do |line| 54 | new_line = line.downcase.gsub(" ", "") 55 | 56 | @regex.each do |el| 57 | new_line = new_line.gsub(el, "") 58 | end 59 | 60 | @lines_bot.push(new_line) 61 | end 62 | end 63 | 64 | def login 65 | @client << "USER #{@nickname} localhost localhost #{@nickname}\n" 66 | @client << "NICK #{@nickname}\n" 67 | end 68 | 69 | def joinChannel(channel : String) 70 | @client << "JOIN #{channel}\n" 71 | end 72 | 73 | def joinAllChannels 74 | @channels.each do |el| 75 | joinChannel("#" + el.to_s) 76 | end 77 | end 78 | 79 | def sendPrivateMessage(channel : String, text : String) 80 | @client << "PRIVMSG #{channel} :#{text}\n" 81 | end 82 | 83 | def answer(message : FastIRC::Message) 84 | channel = message.params[0].gsub("#", "") 85 | msg = message.params[1].downcase.gsub(" ", "") 86 | @regex.each do |el| 87 | msg = msg.gsub(el, "") 88 | end 89 | 90 | if (@prev_line[channel]? == false) 91 | @prev_line[channel] = 0 92 | end 93 | 94 | found = false 95 | i = 0 96 | @lines_bot.each do |line| 97 | if (line == msg) 98 | found = true 99 | break 100 | end 101 | i += 1 102 | end 103 | 104 | if (found) 105 | found = false 106 | @used_times += 1 107 | if (i == (@lines_bot.size - 1)) 108 | @prev_line[channel] = 0 109 | return 110 | end 111 | if (i < @prev_line[channel]) 112 | i_old = i 113 | i = 0 114 | @lines_bot.each do |line| 115 | if (i < @prev_line[channel]) 116 | i += 1 117 | next 118 | end 119 | puts line 120 | if (line == msg) 121 | found = true 122 | break 123 | end 124 | i += 1 125 | end 126 | if (found) 127 | if (i == (@lines_bot.size - 1)) 128 | @prev_line[channel] = 0 129 | else 130 | @prev_line[channel] = i + 1 131 | sendPrivateMessage(message.params[0], @lines_normal[@prev_line[channel]]) 132 | end 133 | else 134 | @prev_line[channel] = i_old + 1 135 | sendPrivateMessage(message.params[0], @lines_normal[@prev_line[channel]]) 136 | end 137 | else 138 | @prev_line[channel] = i + 1 139 | sendPrivateMessage(message.params[0], @lines_normal[@prev_line[channel]]) 140 | end 141 | return 142 | end 143 | return 144 | end 145 | 146 | def run 147 | loadAndParse() 148 | @client = TCPSocket.new(@server, @port, nil, @connection_timeout) 149 | irc_reader = FastIRC::Reader.new(@client) 150 | 151 | loop do 152 | Signal::INT.trap do 153 | puts "\nCTRL-C handler here!" 154 | @client << "QUIT\n" 155 | @client.close 156 | puts "Bot was used #{@used_times} times." 157 | exit 158 | end 159 | 160 | if (@logged_in != true) 161 | login 162 | joinAllChannels 163 | @logged_in = true 164 | end 165 | 166 | while message = irc_reader.next 167 | puts message.to_s 168 | case (message.command) 169 | when "PING" 170 | @client << "PONG :#{message.params[0]}\n" 171 | break 172 | when "KICK" 173 | if (message.params[0] == @nickname) 174 | puts "Oops, I'm kicked!" 175 | end 176 | break 177 | when "PRIVMSG" 178 | temp_msg = message.params[1].gsub(" ", "") 179 | @regex.each do |el| 180 | temp_msg = temp_msg.gsub(el, "") 181 | end 182 | if (temp_msg == "ктотакой#{@nickname}" || temp_msg == "актотакой#{@nickname}") 183 | sendPrivateMessage(message.params[0], "Я - самый полезный бот. Кто не согласен, тот будет построен и зарыт.") 184 | @used_times += 1 185 | elsif (temp_msg == "кудастремятсяжидомайдауны" || temp_msg == "кудастремятсяжидомайдуны") 186 | sendPrivateMessage(message.params[0], "На Белград!") 187 | @used_times += 1 188 | elsif (temp_msg[0..3] == "~inv") 189 | temp_msg = temp_msg.sub("~inv") { "" } 190 | sendPrivateMessage(message.params[0], "Захожу в #{temp_msg}...") 191 | joinChannel(temp_msg) 192 | @used_times += 1 193 | elsif (temp_msg[0..5] == "~leave") 194 | sendPrivateMessage(message.params[0], "Vote Kick ещё не работает :c") 195 | @used_times += 1 196 | else 197 | answer(message) 198 | end 199 | break 200 | else 201 | break 202 | end 203 | end 204 | end 205 | @client << "QUIT\n" 206 | @client.close 207 | end 208 | end 209 | 210 | bychara = Bycharabot.new 211 | 212 | bychara.run 213 | --------------------------------------------------------------------------------