diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48fb8a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.log +*.lock +*.DS_Store +*.pstore \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..1a7213f --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' + +gem 'telegram-bot-ruby' \ No newline at end of file diff --git a/kabanchiki_bot.rb b/kabanchiki_bot.rb new file mode 100644 index 0000000..5b24a41 --- /dev/null +++ b/kabanchiki_bot.rb @@ -0,0 +1,38 @@ +require 'telegram/bot' +require_relative './lib/kabanchiki' +require_relative './lib/telegram_bot_api_patch' + +puts "[#{Time.now}] Bot started" +Telegram::Bot::Client.run(ENV['TOKEN']) do |bot| + bot.listen do |message| + case message + when Telegram::Bot::Types::CallbackQuery + chat_id = message.message.chat.id + game = Kabanchiki.games[chat_id] + + if message.data['πŸ—'] + if game + game.new_bet(message.from.username, message.data, message.id) + else + bot.api.answer_callback_query( + callback_query_id: message.id, + text: "Π­Ρ‚ΠΈ ΠΊΠ°Π±Π°Π½Ρ‡ΠΈΠΊΠΈ ΡƒΠΆΠ΅ подскочили!" + ) + end + end + + when Telegram::Bot::Types::Message + case message.text + when '/bet@KabanchikiBot' + if Kabanchiki.games[message.chat.id] + bot.api.send_message(chat_id: message.chat.id, text: 'ΠšΠ°Π±Π°Π½Ρ‡ΠΈΠΊΠΈ Π΅Ρ‰Ρ‘ Π½Π° подскокС...') + else + game = Kabanchiki.new(bot, message.chat.id) + Thread.start{ game.countdown } + end + when '/top@KabanchikiBot' + bot.api.send_message(chat_id: message.chat.id, text: Kabanchiki.chat_top(message.chat.id)) + end + end + end +end \ No newline at end of file diff --git a/kabanchiki_bot.service b/kabanchiki_bot.service new file mode 100644 index 0000000..1072af9 --- /dev/null +++ b/kabanchiki_bot.service @@ -0,0 +1,16 @@ +# sudo cp kabanchiki_bot.service /lib/systemd/system -v +# sudo systemctl enable kabanchiki_bot.service +# sudo systemctl start kabanchiki_bot.service +[Unit] +Description=Kabanchiki bot + +[Service] +User=ubuntu +Group=ubuntu +WorkingDirectory=/home/ubuntu/kabanchiki_bot +Restart=always +Environment="TOKEN=bot_token" +ExecStart=/usr/bin/ruby kabanchiki_bot.rb + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/lib/kabanchiki.rb b/lib/kabanchiki.rb new file mode 100644 index 0000000..e9a9e89 --- /dev/null +++ b/lib/kabanchiki.rb @@ -0,0 +1,126 @@ +require 'pstore' + +class Kabanchiki + + class << self + def games + @@chats ||= {} + end + + def store + @@store ||= PStore.new("#{__dir__}/kabanchiki_bot.pstore") + end + + def chat_top(chat_id) + text = "Π’ΠΎΠΏ Ρ‡Π°Ρ‚Π°: \n\n" + store.transaction(true) do + users = (store[chat_id] || {}).sort_by{|k, v| -v} + users.each{|u| text << "#{u.first} : #{u.last}\n"} unless users.empty? + end + text + end + end + + attr_accessor :bot, :chat_id, :bets, :kabanchiki, :started_at, :message_id, :timer + + def initialize(bot, chat_id) + @bot = bot + @chat_id = chat_id + @bets = {} + @kabanchiki = ['πŸ— 1', 'πŸ— 2', 'πŸ— 3'] + self.class.games[chat_id] = self + @message_id = nil + end + + def countdown + self.message_id = bot.api.send_message( + chat_id: chat_id, + text: 'ΠšΡ‚ΠΎ подскочСт ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ?', + reply_markup: build_buttons + ).dig('result', 'message_id') + 3.downto(0).each do |t| + self.timer = t + bot.api.edit_message_reply_markup( + chat_id: chat_id, + message_id: message_id, + reply_markup: build_buttons + ) + sleep 3 + end + race + end + + def new_bet(username, data, callback_query_id) + bets[username] = data + bot.api.answer_callback_query( + callback_query_id: callback_query_id, + text: "ΠšΠ°Π±Π°Π½Ρ‡ΠΈΠΊ #{data} Π²Ρ‹Π±Ρ€Π°Π½!" + ) + end + + def race + result = [] + 3.times do |t| + places = [1, 2, 3].shuffle + text = "Погнали!\n" + kabanchiki.each do |kaban| + place = places.pop + text << (' . ' * place) << kaban + text << "\n" + result[place - 1] = kaban + end + text << (" . " * (t + 1)) << "\n" + bot.api.edit_message_text(chat_id: chat_id, message_id: message_id, text: text) + sleep 1.5 + end + + award result.first + end + + def award(winner) + result = "ΠšΠ°Π±Π°Π½Ρ‡ΠΈΠΊ #{winner} подскочил ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ! \n\n" + right_bets = [] + bets.each do |user, bet| + right_bets << user if bet === winner + end + + unless right_bets.empty? + result << right_bets.join(', ') + result << ' поставил(ΠΈ) Π½Π° ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ³ΠΎ ΠΊΠ°Π±Π°Π½Ρ‡ΠΈΠΊΠ°!' + update_chat_top(right_bets) + end + + bot.api.send_message(chat_id: chat_id, text: result) + Kabanchiki.games[chat_id] = nil + end + + def build_buttons + buttons = [] + kabanchiki.each do |kaban| + text = bets.size > 0 ? "#{kaban} (#{bets.values.count(kaban)})" : kaban + buttons << Telegram::Bot::Types::InlineKeyboardButton.new( + text: text, + callback_data: kaban + ) + end + + buttons << Telegram::Bot::Types::InlineKeyboardButton.new( + text: "ΠšΠ°Π±Π°Π½Ρ‡ΠΈΠΊΠΈ мСтнутся Ρ‡Π΅Ρ€Π΅Π· #{timer}", + callback_data: 'kabanchiki_timer' + ) + Telegram::Bot::Types::InlineKeyboardMarkup.new(inline_keyboard: buttons) + end + + def update_chat_top(users) + store = self.class.store + store.transaction do + new_top = {} + old_top = store[chat_id] || {} + users.each do |user| + new_top[user] = old_top[user].to_i + 1 + end + store[chat_id] = old_top.merge(new_top) + end + end + +end diff --git a/lib/telegram_bot_api_patch.rb b/lib/telegram_bot_api_patch.rb new file mode 100644 index 0000000..ffbfdd5 --- /dev/null +++ b/lib/telegram_bot_api_patch.rb @@ -0,0 +1,15 @@ +module Telegram + module Bot + class Api + def call(endpoint, raw_params = {}) + params = build_params(raw_params) + response = conn.post("/bot#{token}/#{endpoint}", params) + if response.status == 200 + JSON.parse(response.body) + else + puts "[#{Time.now}] API error: #{response.status} #{response.body}" + end + end + end + end +end