Skip to content

Commit

Permalink
v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
printercu committed Feb 22, 2016
0 parents commit 37a63f7
Show file tree
Hide file tree
Showing 29 changed files with 1,333 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
2 changes: 2 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--color
--require spec_helper
27 changes: 27 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Rails: {Enabled: true}

Style/Alias: {Enabled: false}
Style/AlignParameters:
# Disable, till rubocop supports combination of styles.
# Use one of this styles where appropriate, keep it clean, compact and readable.
Enabled: false
# EnforcedStyle:
# - with_first_parameter
# - with_fixed_indentation
Style/ClosingParenthesisIndentation: {Enabled: false}
Style/Documentation: {Enabled: false}
Style/DotPosition: {EnforcedStyle: trailing}
Style/IfUnlessModifier: {Enabled: false}
Style/ModuleFunction: {Enabled: false}
Style/MultilineOperationIndentation: {EnforcedStyle: indented}
Style/NestedParenthesizedCalls: {Enabled: false}
Style/PredicateName: {Enabled: false}
Style/SignalException: {EnforcedStyle: only_raise}
Style/SpaceInsideHashLiteralBraces: {EnforcedStyle: no_space}
Style/TrailingCommaInArguments: {Enabled: false}
Style/TrailingCommaInLiteral: {EnforcedStyleForMultiline: comma}

Metrics/AbcSize: {Max: 21}
Metrics/LineLength: {Max: 100}
Metrics/MethodLength: {Max: 30}
Metrics/CyclomaticComplexity: {Max: 8}
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: ruby
cache: bundler
rvm:
- 2.2.3
notifications:
email: false
15 changes: 15 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
source 'https://rubygems.org'
gemspec

group :development do
gem 'sdoc', '~> 0.4.1'
gem 'pry', '~> 0.10.1'
gem 'pry-byebug', '~> 3.2.0'

gem 'rspec', '~> 3.3.0'
gem 'rspec-its', '~> 1.1.0'

gem 'rubocop', '~> 0.37.0'

gem 'coveralls', '~> 0.8.2', require: false
end
184 changes: 184 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Telegram::Bot

[![Gem Version](https://badge.fury.io/rb/telegram-bot.svg)](http://badge.fury.io/rb/telegram-bot)
[![Code Climate](https://codeclimate.com/github/printercu/telegram-bot/badges/gpa.svg)](https://codeclimate.com/github/printercu/telegram-bot)
[![Build Status](https://travis-ci.org/printercu/telegram-bot.svg)](https://travis-ci.org/printercu/telegram-bot)

Tools for developing bot for Telegram. Best used with Rails, but can be be used in
standalone app. Supposed to be used in webhook-mode in production, and poller mode
in development, but you can use poller in production if you want.

Package contains:

- Ligthweight client to bot API (with fast and thread-safe
[httpclient](https://github.com/nahi/httpclient) is under the hood.)
- Controller with message parser. Allows to write separate methods for each command.
- Middleware and routes helpers for production env.
- Poller with automatic source-reloader for development env.
- Rake tasks to update webhook urls.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'telegram-bot'
```

And then execute:

$ bundle

Or install it yourself as:

$ gem install telegram-bot

## Usage

### Configuration

Add `telegram` section into `secrets.yml`:

```yml
telegram:
bots:
# just set the token
chat: TOKEN_1
# or add username to support commands with mentions (/help@ChatBot)
auction:
token: TOKEN_2
username: ChatBot

# Single bot can be specified like this
bot: TOKEN
# or
bot:
token: TOKEN
username: SomeBot
```
### Client
From now clients will be accessible with `Telegram.bots[:chat]` or `Telegram.bots[:auction]`.
Single bot can be accessed with `Telegram.bot` or `Telegram.bots[:default]`.

You can create clients manually with `Telegram::Bot.new(token, username)`.
Username is optional and used only to parse commands with mentions.

Client has all available methods in underscored style
(`answer_inline_query` instead of `answerInlineQuery`).
All this methods just post given params to specific URL.

```ruby
bot.send_message chat_id: chat_id, text: 'Test'
```

### Controller

```ruby
class Telegram::WebhookController < Telegram::Bot::UpdatesController
# use callbacks like in any other controllers
around_action :set_locale
# Every update can have one of: message, inline_query & chosen_inline_result.
# Define method with same name to respond to this updates.
def message(message)
# message can be also accessed via instance method
message == self.payload # true
# store_message(message['text'])
end
# Define public methods to respond to commands.
# Command arguments will be parsed and passed to the method.
# Be sure to use splat args and default values to not get errors when
# someone passed more or less arguments in the message.
#
# For some commands like /message or /123 method names should start with
# `on_` to avoid conflicts.
def start(data = nil, *)
# do_smth_with(data)

# There are `chat` & `from` shortcut methods.
response = from ? "Hello #{from['username']}!" : 'Hi there!'
# There is `reply_with` helper to set basic fields
# like `reply_to_message` & `chat_id`.
reply_with :message, text: response
end

private

def set_locale(&block)
I18n.with_locale(locale_for_update, &block)
end

def locale_for_update
if from
# locale for user
elsif chat
# locale for chat
end
end
end
```

### Routes

Use `telegram_webhooks` helper to add routes. It will create routes for bots
at "telegram/#{bot.token}" path.

```ruby
# Create routes for all Telegram.bots to use same controller:
telegram_webhooks TelegramController

# Or pass custom bots usin any of supported config options:
telegram_webhooks TelegramController,
bot,
{token: token, username: username},
other_bot_token

# Use different controllers for each bot:
telegram_webhooks bot => TelegramChatController,
other_bot => TelegramAuctionController

# telegram_webhooks creates named routes.
# Route name depends on `Telegram.bots`.
# When there is single bot it will use 'telegram_webhook'.
# When there are it will use bot's key in the `Telegram.bots` as prefix
# (eg. `chat_telegram_webhook`).
# You can override this options or specify others:
telegram_webhooks TelegramController, as: :my_webhook
telegram_webhooks bot => [TelegramChatController, as: :chat_webhook],
other_bot => [TelegramAuctionController,
```

For Rack applications you can also use `Telegram::Bot::Middleware` or just
call `.dispatch(bot, update)` on controller.

### Development & Debugging

Use `rake telegram:bot:poller BOT=chat` to run poller. It'll automatically load
changes without restart in development env. This task will not if you don't use
`telegram_webhooks`.

You can run poller manually with
`Telegram::Bot::UpdatesPoller.start(bot, controller_class)`.

### Deploying

Use `rake telegram:bot:set_webhook` to update webhook url for all configured bots.
Certificate can be specified with `CERT=path/to/cert`.

## Development

After checking out the repo, run `bin/setup` to install dependencies.
Then, run `rake spec` to run the tests.
You can also run `bin/console` for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`.
To release a new version, update the version number in `version.rb`,
and then run `bundle exec rake release`, which will create a git tag for the version,
push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/printercu/telegram-bot.
22 changes: 22 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec)

task default: :spec

require 'sdoc'
RDoc::Task.new(:doc) do |rdoc|
rdoc.rdoc_dir = 'doc'

rdoc.title = 'RailsStuff'

rdoc.options << '--markup' << 'markdown'
rdoc.options << '-e' << 'UTF-8'
rdoc.options << '--format' << 'sdoc'
rdoc.options << '--template' << 'rails'
rdoc.options << '--all'

rdoc.rdoc_files.include('README.md')
rdoc.rdoc_files.include('lib/**/*.rb')
end
7 changes: 7 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env ruby

require 'bundler/setup'
require 'telegram/bot'

require 'pry'
Pry.start
14 changes: 14 additions & 0 deletions bin/git-hooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

pattern=$(echo -n '\.rb
\.gemspec
\.jbuilder
\.rake
config\.ru
Gemfile
Rakefile' | tr "\\n" '|')

files=`git diff --cached --name-status | grep -E "^[AM].*($pattern)$" | cut -f2-`
if [ -n "$files" ]; then
bundle exec rubocop $files --force-exclusion
fi
8 changes: 8 additions & 0 deletions bin/install_git_hooks
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env ruby

root = File.expand_path('../../', __FILE__)
hooks_dir = "#{root}/bin/git-hooks"

`ls -1 #{hooks_dir}`.each_line.map(&:strip).each do |file|
`ln -sf #{hooks_dir}/#{file} #{root}/.git/hooks/#{file}`
end
8 changes: 8 additions & 0 deletions bin/setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

bundle install
bin/install_git_hooks

# Do any other automated setup that you need to do here
22 changes: 22 additions & 0 deletions lib/tasks/telegram-bot.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace :telegram do
namespace :bot do
desc 'Run poller'
task poller: :environment do
console = ActiveSupport::Logger.new(STDERR)
Rails.logger.extend ActiveSupport::Logger.broadcast console
Telegram::Bot::UpdatesPoller.start(ENV['BOT'].try!(:to_sym) || :default)
end

desc 'Set webhook urls for all bots'
task set_webhook: :environment do
routes = Rails.application.routes.url_helpers
cert_file = ENV['CERT']
cert = File.open(cert_file) if cert_file
Telegram.bots.each_value do |bot|
route_name = Telegram::RoutesHelper.route_name_for_bot(bot)
url = routes.send("#{route_name}_url")
bot.set_webhook(url: url, certificate: cert)
end
end
end
end
Loading

0 comments on commit 37a63f7

Please sign in to comment.