Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements #14

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,34 @@ Simple Termin cancelation monitoring for the Berliner offices :eyeglasses:

## Installation

Add this line to your application's Gemfile:
Install it directly from github:

```ruby
gem 'termin_de'
```

And then execute:

$ bundle

Or install it yourself as:

$ gem install termin_de
$ gem install specific_install
$ gem specific_install -l https://github.com/Strech/termin_de.git

## Usage

```
Usage: termin [options]
Burgeramt termin monitor. Version 0.1.0
Usage: termin_de [options]
-b, --before=<date> Trigger only on date earlier than given date
-c, --execute=<command> Run given command with %{date} and %{link} replacements
-s, --service=<id> Id of the requested service
-u, --burgeramt=<id> Id of the burgeramt
-u, --burgeramt=<bid> Id of the burgeramt(s) (comma separated)
-i, --interval=<sec> How long to wait between requests in seconds
--dry-run Run on saved examples
--verbose Print more information during run
--version Display the version
```

By default `termin_de` will look for an appointment to get a Personalausweis (service=) in all Bürgerämtern.

By default `termin_de` will find appointments for the current and next month (and not any further). If you are looking only appointments before an even shorter date then use `-b` and give the date in the format `YYYY-mm-dd`.

To perform a different or more specific search, you need to look-up the service id of the service you want (see [https://service.berlin.de/dienstleistungen/]) and pass a list of Bürgerämtern which you want to search (see [https://service.berlin.de/standorte/buergeraemter/] for the Bürgerämter, or the complete list at [https://service.berlin.de/standorte/]).

As an example of the `-c` switch, if you are running WSL under Windows you can a browser open automatically by using `-c "wslview '%{link}'"`.

## Examples

Basically you can sit down, relax, brew some :coffee: and watch at output.
Expand Down Expand Up @@ -57,9 +59,19 @@ Use `--dry-run` option for local sandbox. Sample has 2 available dates `2015-11-

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
Clone this repo locally: `git clone https://github.com/Strech/termin_de`

After checking out the repo, run `bin/setup` to install dependencies.

Then, run `bundle exec rake spec` to run the tests.

Run the local version of the code using `bundle exec bin/termin_de`

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 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).
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

Expand Down
2 changes: 2 additions & 0 deletions lib/termin_de/calendar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def download_latest_calendar
curl = Curl::Easy.new
curl.enable_cookies = true
curl.follow_location = true

TerminDe.logger.debug "Starting HTTP GET to url: #{url}"
curl.url = url
curl.http_get
Nokogiri.parse(curl.body_str)
Expand Down
42 changes: 29 additions & 13 deletions lib/termin_de/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,29 @@
module TerminDe
# command line interface
class Cli
DEFAULT_DATE = Date.new(3000, 0o1, 0o1)
DEFAULT_DATE = Date.new(Date.today.year, Date.today.month + 2, 1)
DEFAULT_DRY_RUN = false
# default request for id card
DEFAULT_SERVICE = '120703'
BURGERAMT_IDS = [
# ALL '122210,122217,327316,122219,327312,122227,122231,327346,122238,122243,327348,122252,329742,122260,329745,122262,329748,122254,329751,122271,327278,122273,122277,327276,122280,327294,122282,327290,122284,327292,122291,327270,122285,327266,122286,327264,122296,327268,327262,325657,150230,329760,122301,327282,122297,327286,122294,327284,122312,329763,122304,327330,122311,327334,122309,327332,317869,324434,122281,327352,122279,122276,327324,122274,327326,122267,329766,122246,327318,122251,327320,327653,122257,327322,122208,122226'
'122243', # Friedrichshain Frankfurter
'122238', # Friedrichshain Schlesisches Tor
'122260', # Lichtenberg Moellendorfstr
'122262' # Lichtenberg TierparkCenter
]

# NOTE : We don't want to be limited by service protection
REQUEST_INTERVAL_IN_SECONDS = 60

DEFAULT_COMMAND = nil

# By default we query all Bürgerämter
BURGERAMT_IDS = '122210,122217,327316,122219,327312,122227,122231,327346,122238,122243,327348,122252,329742,122260,329745,122262,329748,122254,329751,122271,327278,122273,122277,327276,122280,327294,122282,327290,122284,327292,122291,327270,122285,327266,122286,327264,122296,327268,327262,325657,150230,329760,122301,327282,122297,327286,122294,327284,122312,329763,122304,327330,122311,327334,122309,327332,317869,324434,122281,327352,122279,122276,327324,122274,327326,122267,329766,122246,327318,122251,327320,327653,122257,327322,122208,122226'
#[
# '122243', # Friedrichshain Frankfurter
# '122238', # Friedrichshain Schlesisches Tor
# '122260', # Lichtenberg Moellendorfstr
# '122262' # Lichtenberg TierparkCenter
#]
DEFAULT_VERBOSITY = false

def initialize(argv)
@argv = argv
@options = Options.new(DEFAULT_DATE, DEFAULT_DRY_RUN, DEFAULT_SERVICE, BURGERAMT_IDS)
@options = Options.new(DEFAULT_DATE, DEFAULT_DRY_RUN, DEFAULT_SERVICE, BURGERAMT_IDS, DEFAULT_COMMAND, DEFAULT_VERBOSITY, REQUEST_INTERVAL_IN_SECONDS)
end

def start
Expand All @@ -30,7 +38,7 @@ def start

private

Options = Struct.new(:before_date, :dry_run, :service, :burgeramt, :command) do
Options = Struct.new(:before_date, :dry_run, :service, :burgeramt, :command, :verbose, :request_interval_in_seconds) do
def command_given?
!command.nil?
end
Expand All @@ -40,8 +48,8 @@ def command_given?

def opt_parser
OptionParser.new do |parser|
parser.banner = "Burgeramt termin monitor\nUsage: termin [options]"
parser.version = VERSION
parser.banner = "Burgeramt termin monitor. Version #{parser.version}\nUsage: termin_de [options]"

parser.on('-b', '--before=<date>', String, 'Trigger only on date earlier than given date') do |date|
@options.before_date = begin
Expand All @@ -59,16 +67,24 @@ def opt_parser
@options.service = !id.nil? ? id : DEFAULT_SERVICE
end

parser.on('-u', '--burgeramt=<bid>', String, 'Id of the burgeramt') do |id|
parser.on('-u', '--burgeramt=<bid>', String, 'Id of the burgeramt(s) (comma separated)') do |id|
@options.burgeramt = id.nil? ? BURGERAMT_IDS : id
end

parser.on('-i', '--interval=<sec>', String, 'How long to wait between requests in seconds') do |interval|
@options.request_interval_in_seconds = interval.nil? ? REQUEST_INTERVAL_IN_SECONDS : interval
end

parser.on('--dry-run', 'Run on saved examples') do
@options.dry_run = true
end

parser.on('--verbose', 'Print more information during run') do
@options.verbose = true
end

parser.on_tail('--version', 'Display the version') do
puts "Burgeramt termin monitor. Version #{parser.version}"
puts parser.version
exit
end
end
Expand Down
26 changes: 14 additions & 12 deletions lib/termin_de/loop.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
# frozen_string_literal: true

require 'logger'
require 'yaml'

module TerminDe
# Endless loop for querying the burgeramt webpage
class Loop
# NOTE : We don't want to be limited by service protection
REQUEST_INTERVAL_IN_SECONDS = 60

def initialize(options)
@options = options
@fails = 0

@logger = Logger.new(STDOUT)
@logger.datetime_format = '%Y-%m-%d %H:%M:%S'
@logger.level = Logger::INFO
TerminDe.logger.datetime_format = '%Y-%m-%d %H:%M:%S'
TerminDe.logger.level = options.verbose ? Logger::DEBUG : Logger::INFO

TerminDe.logger.debug "Starting with options:\n#{options.to_h.to_yaml}"

end

def run
Expand All @@ -24,38 +25,39 @@ def run
if calendar.earlier?
termin_found(calendar.earlier_termin)
else
@logger.info 'Nothing ...'
TerminDe.logger.info 'Nothing ...'
end

sleep(REQUEST_INTERVAL_IN_SECONDS)
sleep(@options.request_interval_in_seconds)
end
end

private

def infinitly
loop do
@logger.info "Looking for available slots before #{@options.before_date}"
TerminDe.logger.info "Looking for available slots for service #{@options.service}, in #{@options.burgeramt == Cli::BURGERAMT_IDS ? 'all buergeramts' : "buergeramt #{@options.burgeramt}"} before #{@options.before_date}"
begin
yield
rescue Exception => e
# NOTE : Arrrgh, Curb doesn't nest exceptions
raise unless e.class.name =~ /Curl/

@fails += 1
pause_when(@fails)
end
end
end

def pause_when(fails)
num = (Math.log10(fails) * REQUEST_INTERVAL_IN_SECONDS / 2 + REQUEST_INTERVAL_IN_SECONDS).to_i
@logger.warn "Woooops, slow down ... pause for #{num} seconds"
num = (Math.log10(fails) * @options.request_interval_in_seconds / 2 + @options.request_interval_in_seconds).to_i
TerminDe.logger.warn "Woooops, slow down ... pause for #{num} seconds"
sleep(num)
end

def termin_found(termin)
@logger.info "Found new [#{termin.date}] → #{termin.link}"
TerminDe.logger.info "Found new [#{termin.date}] → #{termin.link}"
print "\a"
`#{@options.command % termin.to_h}` if @options.command_given?
end
end
Expand Down
5 changes: 5 additions & 0 deletions lib/termin_de/termin.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# frozen_string_literal: true

module TerminDe

def self.logger
@@logger ||= Logger.new(STDOUT)
end

# simple termin object to hold date, link and the service
class Termin
attr_reader :date
Expand Down