flycal-cli 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8efca78d1d82f9e3310cbd90a29a95ad52fbf9fff714d3aada8321c999bfaa71
4
- data.tar.gz: 749f5417dfd3cc780c78e55524aa0acabea9b8fc28f07614d8faa25e7920253b
3
+ metadata.gz: c7e777c9b4698b273770ea0d9a70edf232ffe70f2e6bd9d32ab65818ca0f5cb5
4
+ data.tar.gz: 5d62d5fede48b31930a6a652c8b4f165a0f82315eb85e3fb5be885e56ffc2ae7
5
5
  SHA512:
6
- metadata.gz: be1d24bae7776ca94842c9edd5116544b750846ccc169bd57ba6720dc1b63904eaad92fb2f33ace8f668a8580352ea2ff530532c5262bbc83d44f4f92521b324
7
- data.tar.gz: 2d89f80c2b486f102b8ad6edf178dd71126fd78549a49caecc17a5bc0254827f2d0ed07cb727e2cbc18c0b3bf19cc64bbca04846f8a72a00b82d7cb77495273c
6
+ metadata.gz: c1d95fcb97e10fa0c1144e15c7e205cb693d2c48847dc96569cb718c8899c5ecb3479504b4c19b3315dd8c74ecbcbc9510e99f2070a4c392ae206c51dba395dd
7
+ data.tar.gz: 6d9d08601b3d78d1aa8d3520b2f0102517b80be6ac708d0d036e3e5558d2548c1a57613f9b3121ebb12329f564a682b71843ac96b5c56a07cdf578f4dcab8f71
data/README.md CHANGED
@@ -1,139 +1,156 @@
1
1
  # flycal-cli
2
2
 
3
- CLI per accedere ai calendari Google da riga di comando.
3
+ A command-line tool to access and search Google Calendar events. Connect your Google account, choose a default calendar, and search events with flexible date ranges and text filters.
4
4
 
5
- ## Installazione
5
+ ## Requirements
6
+
7
+ - Ruby 3.1 or later
8
+ - A Google Cloud project with Calendar API enabled
9
+
10
+ ## Installation
6
11
 
7
12
  ```bash
8
13
  gem install flycal-cli
9
14
  ```
10
15
 
11
- Oppure aggiungi al tuo Gemfile:
16
+ Or add to your Gemfile:
12
17
 
13
18
  ```ruby
14
19
  gem "flycal-cli"
15
20
  ```
16
21
 
17
- ## Configurazione iniziale
22
+ Then run `bundle install`.
23
+
24
+ ## Setup
18
25
 
19
- Prima di usare flycal, devi creare credenziali OAuth nel Google Cloud Console:
26
+ Before using flycal, you need OAuth credentials from Google Cloud Console:
20
27
 
21
- 1. Vai su [Google Cloud Console - Credenziali](https://console.cloud.google.com/apis/credentials)
22
- 2. Crea un progetto (o usa uno esistente)
23
- 3. Abilita l'**API Google Calendar** (API e serviziLibreriaCerca "Google Calendar API")
24
- 4. Crea credenziali **Applicazione desktop** (OAuth 2.0 Client IDs)
25
- 5. Aggiungi questo URI come redirect autorizzato:
28
+ 1. Go to [Google Cloud Console - Credentials](https://console.cloud.google.com/apis/credentials)
29
+ 2. Create a project or select an existing one
30
+ 3. Enable the **Google Calendar API** (APIs & ServicesLibrarysearch for "Google Calendar API")
31
+ 4. Create **Desktop app** credentials (OAuth 2.0 Client IDs)
32
+ 5. Add this URI as an authorized redirect:
26
33
  ```
27
34
  http://127.0.0.1:9292/oauth2callback
28
35
  ```
29
- 6. Scarica il file JSON e salvalo come `~/.flycal/credentials.json`
36
+ 6. Download the JSON file and save it as `~/.flycal/credentials.json`
30
37
 
31
- ## Comandi
38
+ ## Commands
32
39
 
33
- ### `flycal login`
40
+ ### login
34
41
 
35
- Connetti al tuo account Google. Se non sei connesso, verrà generato un link da aprire nel browser per completare l'autenticazione OAuth.
42
+ Connect to your Google account. Opens a browser for OAuth authentication when not yet connected.
36
43
 
37
44
  ```bash
38
45
  flycal login
39
46
  ```
40
47
 
41
- ### `flycal calendars`
48
+ If already connected, the command reports the current status and suggests running `flycal calendars` to set the default calendar.
42
49
 
43
- Mostra la lista dei calendari disponibili e permette di selezionare il calendario di default. La selezione è scorrevole (usa le frecce per navigare).
50
+ ### logout
51
+
52
+ Disconnect from your Google account and remove stored tokens.
44
53
 
45
54
  ```bash
46
- flycal calendars
55
+ flycal logout
47
56
  ```
48
57
 
49
- ### `flycal logout`
58
+ ### calendars
50
59
 
51
- Disconnetti dall'account Google.
60
+ List available calendars and set the default one. Uses an interactive scrollable menu (arrow keys to navigate, type to filter).
52
61
 
53
62
  ```bash
54
- flycal logout
63
+ flycal calendars
55
64
  ```
56
65
 
57
- ### `flycal search`
66
+ The default calendar is used by the search command when no calendar is specified.
67
+
68
+ ### search
58
69
 
59
- Cerca eventi nei calendari.
70
+ Search for events in your calendar(s). Supports flexible date ranges and text filtering.
60
71
 
61
72
  ```bash
62
- flycal search --from 2025-02-01 --to 2025-02-28
63
- flycal search -f 2025-02-01 -t 2025-02-28 --description "riunione"
64
- flycal search -f 2025-02-01T09:00 -t 2025-02-28T18:00 -c "Lavoro"
73
+ flycal search
74
+ flycal search --in 30days --description placeholder
75
+ flycal search -f 2025-03-01 -t 2025-03-31 -c "Work"
76
+ flycal search -i 2months -d placeholder
65
77
  ```
66
78
 
67
- Opzioni:
68
- - `-f, --from`: Data/ora inizio (es. `2025-01-01` o `2025-01-01T09:00`)
69
- - `-t, --to`: Data/ora fine
70
- - `-c, --calendar`: Nome o ID del calendario (default: calendario impostato con `flycal calendars`)
71
- - `-d, --description`: Filtra eventi per testo nella descrizione
79
+ **Options:**
72
80
 
73
- ## File di configurazione
81
+ | Option | Short | Description |
82
+ |--------|-------|-------------|
83
+ | `--from` | `-f` | Start date/time. Default: midnight of current day. Format: `2025-01-01` or `2025-01-01T09:00` |
84
+ | `--to` | `-t` | End date/time. Default: 23:59 of the 30th day from today. Format: same as `--from` |
85
+ | `--in` | `-i` | Duration from `--from`, overrides `--to`. Format: `30days`, `48hours`, `2months`, `1year` (no space between number and unit). With space, use quotes: `--in "30 days"` |
86
+ | `--calendar` | `-c` | Calendar name or ID. Default: calendar set via `flycal calendars` |
87
+ | `--description` | `-d` | Filter events by text. Matches events where the string appears in the title or description (case-insensitive, contains) |
74
88
 
75
- I dati vengono salvati in `~/.flycal/`:
89
+ **Time range behavior:**
76
90
 
77
- - `config.yml` - calendario di default (`calendar_default`)
78
- - `credentials.json` - credenziali OAuth (da creare manualmente)
79
- - `tokens.yml` - token di accesso (gestito automaticamente)
91
+ - If neither `--from` nor `--to` is given: searches from today at midnight to 23:59 of the 30th day from today
92
+ - If `--in` is given: `--to` is ignored; the end time is computed from `--from` plus the duration
93
+ - Examples: `--in 30days`, `--in 48hours`, `--in 1months`, `--in 1year`
80
94
 
81
- ## Pubblicazione su RubyGems
95
+ **Output:**
82
96
 
83
- ### Primo caricamento
97
+ Each event is printed as: `Calendar | Start | End | Title`
84
98
 
85
- 1. Crea un account su [rubygems.org](https://rubygems.org) se non ce l'hai
86
- 2. Aggiorna `flycal-cli.gemspec` con i tuoi dati (autori, email, homepage)
87
- 3. Build e push:
99
+ The summary shows:
100
+ - From and To dates used
101
+ - Number of events found
102
+ - Total time occupied (hours, minutes, and working days based on 8-hour days)
88
103
 
89
- ```bash
90
- # Build della gem
91
- gem build flycal-cli.gemspec
104
+ ## Configuration
92
105
 
93
- # Push (ti chiederà email e password RubyGems)
94
- gem push flycal-cli-0.1.0.gem
95
- ```
106
+ Data is stored in `~/.flycal/`:
96
107
 
97
- ### Versioni successive
108
+ | File | Purpose |
109
+ |------|---------|
110
+ | `config.yml` | Default calendar ID and other settings |
111
+ | `credentials.json` | OAuth credentials (created manually from Google Cloud Console) |
112
+ | `tokens.yml` | Access tokens (managed automatically) |
98
113
 
99
- 1. Aggiorna la versione in `lib/flycal_cli/version.rb`
100
- 2. Commit e tag:
114
+ ## Publishing to RubyGems
101
115
 
102
- ```bash
103
- git add .
104
- git commit -m "Release v0.2.0"
105
- git tag v0.2.0
106
- git push origin main
107
- git push origin v0.2.0
108
- ```
116
+ ### First release
109
117
 
110
- 3. Build e push:
118
+ 1. Create an account at [rubygems.org](https://rubygems.org) if needed
119
+ 2. Update `flycal-cli.gemspec` with your author, email, and homepage
120
+ 3. Build and push:
111
121
 
112
122
  ```bash
113
123
  gem build flycal-cli.gemspec
114
- gem push flycal-cli-0.2.0.gem
124
+ gem push flycal-cli-0.1.0.gem
115
125
  ```
116
126
 
117
- ### Usando `rake release` (raccomandato)
127
+ ### Subsequent releases
118
128
 
119
- Aggiungi al Rakefile:
129
+ 1. Update the version in `lib/flycal_cli/version.rb`
130
+ 2. Build and push:
120
131
 
121
- ```ruby
122
- require "bundler/gem_tasks"
132
+ ```bash
133
+ gem build flycal-cli.gemspec
134
+ gem push flycal-cli-X.Y.Z.gem
123
135
  ```
124
136
 
125
- Poi:
137
+ 3. Optionally tag and push:
126
138
 
127
139
  ```bash
128
- # Per la prima release
129
- bundle exec rake release
140
+ git tag vX.Y.Z
141
+ git push origin vX.Y.Z
142
+ ```
130
143
 
131
- # Per release successive: aggiorna VERSION e poi
144
+ ### Using rake release
145
+
146
+ With `bundler/gem_tasks` in your Rakefile:
147
+
148
+ ```bash
132
149
  bundle exec rake release
133
150
  ```
134
151
 
135
- `rake release` esegue: build, push su RubyGems, commit, tag e push su git.
152
+ This builds the gem, pushes to RubyGems, and can handle git tagging and pushing.
136
153
 
137
- ## Licenza
154
+ ## License
138
155
 
139
156
  MIT
@@ -43,9 +43,9 @@ module FlycalCli
43
43
  def login
44
44
  unless Config.credentials_exist?
45
45
  raise FlycalCli::Error,
46
- "File credentials non trovato. Crea #{Config.credentials_path} con le credenziali OAuth dal Google Cloud Console.\n" \
47
- "Vai su: https://console.cloud.google.com/apis/credentials\n" \
48
- "Crea credenziali 'Desktop app' e scarica il JSON come credentials.json"
46
+ "Credentials file not found. Create #{Config.credentials_path} with OAuth credentials from Google Cloud Console.\n" \
47
+ "Go to: https://console.cloud.google.com/apis/credentials\n" \
48
+ "Create 'Desktop app' credentials and download the JSON as credentials.json"
49
49
  end
50
50
 
51
51
  token_store = Google::Auth::Stores::FileTokenStore.new(file: Config.tokens_path)
@@ -63,9 +63,9 @@ module FlycalCli
63
63
  return creds
64
64
  end
65
65
 
66
- # Avvia server locale per ricevere il codice
66
+ # Start local server to receive the auth code
67
67
  code = start_redirect_server(authorizer)
68
- raise FlycalCli::Error, "Autenticazione annullata o fallita" if code.nil? || code.empty?
68
+ raise FlycalCli::Error, "Authentication cancelled or failed" if code.nil? || code.empty?
69
69
 
70
70
  authorizer.get_and_store_credentials_from_code(
71
71
  user_id: "flycal_user",
@@ -104,12 +104,12 @@ module FlycalCli
104
104
 
105
105
  if params["error"]
106
106
  res.status = 400
107
- res.body = "<h1>Errore</h1><p>#{params['error']}: #{params['error_description']}</p>"
107
+ res.body = "<h1>Error</h1><p>#{params['error']}: #{params['error_description']}</p>"
108
108
  auth_code = nil
109
109
  elsif params["code"]
110
110
  auth_code = params["code"]
111
111
  res.status = 200
112
- res.body = "<h1>Autenticazione completata!</h1><p>Puoi chiudere questa finestra e tornare al terminale.</p>"
112
+ res.body = "<h1>Authentication complete!</h1><p>You can close this window and return to the terminal.</p>"
113
113
  end
114
114
 
115
115
  Thread.new { server.shutdown }
@@ -120,9 +120,9 @@ module FlycalCli
120
120
  state: state
121
121
  )
122
122
 
123
- puts "\nApri questo link nel browser per autenticarti:\n\n"
123
+ puts "\nOpen this link in your browser to authenticate:\n\n"
124
124
  puts " #{url}\n\n"
125
- puts "Dopo l'autenticazione, tornerai qui automaticamente.\n\n"
125
+ puts "After authentication, you will be redirected back here automatically.\n\n"
126
126
 
127
127
  server.start
128
128
  auth_code
@@ -45,12 +45,26 @@ module FlycalCli
45
45
  def list_all_events(calendar_ids, time_min:, time_max:, query: nil)
46
46
  all_events = []
47
47
 
48
+ # When --description is used: fetch all events and filter client-side to guarantee
49
+ # contains/like behavior. We do not use the API's q param so we can ensure we
50
+ # return all events where the string appears in summary or description (case-insensitive).
48
51
  calendar_ids.each do |cal_id|
49
52
  begin
50
- events = list_events(cal_id, time_min: time_min, time_max: time_max, query: query)
53
+ events = list_events(cal_id, time_min: time_min, time_max: time_max, query: nil)
51
54
  events.each { |e| all_events << { calendar_id: cal_id, event: e } }
52
55
  rescue Google::Apis::Errors::Error => e
53
- warn "Errore nel calendario #{cal_id}: #{e.message}"
56
+ warn "Error in calendar #{cal_id}: #{e.message}"
57
+ end
58
+ end
59
+
60
+ # Filter: only events where summary or description contains the search string (case-insensitive)
61
+ if query && !query.to_s.strip.empty?
62
+ q = query.strip.downcase
63
+ all_events.select! do |item|
64
+ event = item[:event]
65
+ summary = (event.summary || "").downcase
66
+ description = (event.description || "").downcase
67
+ summary.include?(q) || description.include?(q)
54
68
  end
55
69
  end
56
70
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "thor"
4
4
  require "time"
5
+ require "date"
5
6
  require "tty-prompt"
6
7
  require "tty-spinner"
7
8
 
@@ -13,70 +14,70 @@ module FlycalCli
13
14
  true
14
15
  end
15
16
 
16
- desc "login", "Connetti al tuo account Google"
17
+ desc "login", "Connect to your Google account"
17
18
  def login
18
19
  if Auth.logged_in?
19
- puts "✓ Sei già connesso al tuo account Google."
20
- puts "\nEsegui 'flycal calendars' per impostare il calendario di default."
20
+ puts "✓ You are already connected to your Google account."
21
+ puts "\nRun 'flycal calendars' to set the default calendar."
21
22
  return
22
23
  end
23
24
 
24
25
  unless Config.credentials_exist?
25
- puts "Errore: File credentials non trovato."
26
- puts "\nPer configurare flycal:"
27
- puts "1. Vai su https://console.cloud.google.com/apis/credentials"
28
- puts "2. Crea credenziali 'Applicazione desktop' (Desktop app)"
29
- puts "3. Scarica il JSON e salvalo come: #{Config.credentials_path}"
30
- puts "\nAggiungi anche questo URI come redirect autorizzato:"
26
+ puts "Error: Credentials file not found."
27
+ puts "\nTo configure flycal:"
28
+ puts "1. Go to https://console.cloud.google.com/apis/credentials"
29
+ puts "2. Create 'Desktop app' credentials"
30
+ puts "3. Download the JSON and save it as: #{Config.credentials_path}"
31
+ puts "\nAlso add this URI as an authorized redirect:"
31
32
  puts " http://127.0.0.1:9292/oauth2callback"
32
33
  return
33
34
  end
34
35
 
35
36
  begin
36
37
  Auth.login
37
- puts "\n✓ Autenticazione completata con successo!"
38
- puts "\nEsegui 'flycal calendars' per impostare il calendario di default."
38
+ puts "\n✓ Authentication completed successfully!"
39
+ puts "\nRun 'flycal calendars' to set the default calendar."
39
40
  rescue FlycalCli::Error => e
40
- puts "Errore: #{e.message}"
41
+ puts "Error: #{e.message}"
41
42
  exit 1
42
43
  end
43
44
  end
44
45
 
45
- desc "logout", "Disconnetti dall'account Google"
46
+ desc "logout", "Disconnect from Google account"
46
47
  def logout
47
48
  unless Auth.logged_in?
48
- puts "Non sei connesso a nessun account Google."
49
+ puts "You are not connected to any Google account."
49
50
  return
50
51
  end
51
52
 
52
53
  Auth.logout
53
- puts "✓ Disconnesso con successo."
54
+ puts "✓ Disconnected successfully."
54
55
  end
55
56
 
56
- desc "calendars", "Mostra i calendari disponibili e imposta quello di default"
57
+ desc "calendars", "List available calendars and set the default one"
57
58
  def calendars
58
59
  unless Auth.logged_in?
59
- puts "Non sei connesso. Esegui prima 'flycal login'."
60
+ puts "You are not connected. Run 'flycal login' first."
60
61
  exit 1
61
62
  end
62
63
 
63
64
  creds = Auth.credentials
64
65
  service = CalendarService.new(creds)
65
66
 
66
- spinner = TTY::Spinner.new("Caricamento calendari... ", format: :dots)
67
+ spinner = TTY::Spinner.new("Loading calendars... ", format: :dots)
67
68
  spinner.auto_spin
68
69
  calendars = service.list_calendars
69
70
  spinner.stop("✓")
70
71
 
71
72
  if calendars.empty?
72
- puts "Nessun calendario trovato."
73
+ puts "No calendars found."
73
74
  return
74
75
  end
75
76
 
76
- # Costruisci lista per selezione (display => calendar_id)
77
+ # Build selection list (display => calendar_id)
77
78
  default_id = Config.calendar_default
78
79
  choices = calendars.to_h do |cal|
79
- primary = cal.primary ? " (principale)" : ""
80
+ primary = cal.primary ? " (primary)" : ""
80
81
  default = (cal.id == default_id) ? " [default]" : ""
81
82
  summary = cal.summary || cal.id
82
83
  label = "#{summary}#{primary}#{default}"
@@ -85,7 +86,7 @@ module FlycalCli
85
86
 
86
87
  prompt = TTY::Prompt.new
87
88
  selected_id = prompt.select(
88
- "Scegli il calendario di default:",
89
+ "Choose the default calendar:",
89
90
  choices,
90
91
  per_page: 15,
91
92
  filter: true
@@ -94,26 +95,52 @@ module FlycalCli
94
95
  calendar = calendars.find { |c| c.id == selected_id }
95
96
  if calendar
96
97
  Config.calendar_default = calendar.id
97
- puts "\n✓ Calendario di default impostato: #{calendar.summary}"
98
+ puts "\n✓ Default calendar set to: #{calendar.summary}"
98
99
  end
99
100
  end
100
101
 
101
- desc "search", "Cerca eventi nei calendari"
102
- option :calendar, type: :string, aliases: "-c", desc: "Nome o ID del calendario (default: calendario default)"
103
- option :from, type: :string, aliases: "-f", required: true, desc: "Data/ora inizio (es. 2025-01-01 o 2025-01-01T09:00)"
104
- option :to, type: :string, aliases: "-t", required: true, desc: "Data/ora fine (es. 2025-01-31 o 2025-01-31T18:00)"
105
- option :description, type: :string, aliases: "-d", desc: "Filtra per descrizione (testo)"
102
+ desc "search", "Search for events in calendars"
103
+ long_desc <<-LONGDESC
104
+ Search for events in your Google calendar(s).
105
+
106
+ Time range:
107
+ -f, --from DATE Start (default: today midnight)
108
+ -t, --to DATE End (default: 23:59 of day 30)
109
+ -i, --in DURATION Duration from --from, overrides --to.
110
+ Format: 30days, 48hours, 2months, 1year (no space).
111
+ With space use quotes: --in "30 days"
112
+
113
+ Examples:
114
+ flycal search
115
+ flycal search --in 30days -d placeholder
116
+ flycal search -i 1months --description placeholder
117
+ flycal search -f 2025-03-01 --in 2months
118
+ LONGDESC
119
+ option :calendar, type: :string, aliases: "-c", desc: "Calendar name or ID"
120
+ option :from, type: :string, aliases: "-f", desc: "Start (default: today midnight)"
121
+ option :to, type: :string, aliases: "-t", desc: "End (default: 23:59 of day 30)"
122
+ option :in, type: :string, aliases: "-i", desc: "Duration: 30days, 48hours, 2months, 1year (overrides --to)"
123
+ option :description, type: :string, aliases: "-d", desc: "Filter by text in event"
106
124
  def search
107
125
  unless Auth.logged_in?
108
- puts "Non sei connesso. Esegui prima 'flycal login'."
126
+ puts "You are not connected. Run 'flycal login' first."
109
127
  exit 1
110
128
  end
111
129
 
112
- time_min = parse_datetime(options[:from])
113
- time_max = parse_datetime(options[:to], end_of_day: true)
130
+ time_min = options[:from].to_s.empty? ? Date.today.to_time : parse_datetime(options[:from])
131
+ begin
132
+ time_max = if options[:in].to_s.empty?
133
+ options[:to].to_s.empty? ? (Date.today + 30).to_time + 86400 - 1 : parse_datetime(options[:to], end_of_day: true)
134
+ else
135
+ parse_duration_in(options[:in], time_min)
136
+ end
137
+ rescue FlycalCli::Error => e
138
+ puts "Error: #{e.message}"
139
+ exit 1
140
+ end
114
141
 
115
142
  if time_min > time_max
116
- puts "Errore: la data 'from' deve essere prima della data 'to'."
143
+ puts "Error: 'from' date must be before 'to' date."
117
144
  exit 1
118
145
  end
119
146
 
@@ -122,7 +149,7 @@ module FlycalCli
122
149
 
123
150
  calendar_ids = resolve_calendar_ids(service, options[:calendar])
124
151
  if calendar_ids.empty?
125
- puts "Nessun calendario trovato."
152
+ puts "No calendars found."
126
153
  exit 1
127
154
  end
128
155
 
@@ -134,7 +161,7 @@ module FlycalCli
134
161
  )
135
162
 
136
163
  print_events(service, events)
137
- print_summary(events)
164
+ print_summary(events, time_min: time_min, time_max: time_max)
138
165
  end
139
166
 
140
167
  default_task :help
@@ -149,7 +176,29 @@ module FlycalCli
149
176
  else
150
177
  d = Date.parse(str)
151
178
  t = d.to_time
152
- end_of_day ? t + 86400 - 1 : t # 23:59:59 per --to quando è solo data
179
+ end_of_day ? t + 86400 - 1 : t # 23:59:59 for --to when date-only
180
+ end
181
+ end
182
+
183
+ def parse_duration_in(str, from_time)
184
+ # Support both "30days" and "30 days" (no space avoids shell splitting)
185
+ m = str.to_s.strip.match(/\A(\d+)\s*(day|days|d|hour|hours|h|month|months|m|year|years|y)\z/i)
186
+ raise FlycalCli::Error, "Invalid --in format. Use: 30days, 48hours, 2months, 1year (no space, or quote: --in \"30 days\")" unless m
187
+
188
+ n = m[1].to_i
189
+ unit = m[2].downcase
190
+
191
+ case unit
192
+ when "hour", "hours", "h"
193
+ from_time + n * 3600
194
+ when "day", "days", "d"
195
+ from_time + n * 86400
196
+ when "month", "months", "m"
197
+ (from_time.to_date >> n).to_time + (from_time.hour * 3600 + from_time.min * 60 + from_time.sec)
198
+ when "year", "years", "y"
199
+ (from_time.to_date >> (n * 12)).to_time + (from_time.hour * 3600 + from_time.min * 60 + from_time.sec)
200
+ else
201
+ raise FlycalCli::Error, "Invalid unit: #{unit}. Use: days, hours, months, years"
153
202
  end
154
203
  end
155
204
 
@@ -161,15 +210,15 @@ module FlycalCli
161
210
  if default_id
162
211
  return [default_id]
163
212
  end
164
- # Usa calendario principale se disponibile
213
+ # Use primary calendar if available
165
214
  primary = calendar_lists.find(&:primary)
166
215
  return [primary.id] if primary
167
- # Altrimenti primo calendario
216
+ # Otherwise first calendar
168
217
  return [calendar_lists.first.id] if calendar_lists.any?
169
218
  return []
170
219
  end
171
220
 
172
- # Cerca per nome o ID
221
+ # Search by name or ID
173
222
  matches = calendar_lists.select do |cal|
174
223
  cal.id == calendar_name ||
175
224
  (cal.summary && cal.summary.downcase.include?(calendar_name.downcase))
@@ -179,7 +228,7 @@ module FlycalCli
179
228
  end
180
229
 
181
230
  def print_events(service, events)
182
- # Usa lista calendari per i nomi (evita chiamate API extra)
231
+ # Use calendar list for names (avoids extra API calls)
183
232
  calendar_list = service.list_calendars
184
233
  calendar_names = calendar_list.to_h { |c| [c.id, c.summary || c.id] }
185
234
 
@@ -193,7 +242,7 @@ module FlycalCli
193
242
 
194
243
  start_str = format_datetime(start_time)
195
244
  end_str = format_datetime(end_time)
196
- desc = event.summary || "(senza titolo)"
245
+ desc = event.summary || "(no title)"
197
246
  desc = event.description&.slice(0, 80) if event.summary.nil? && event.description
198
247
 
199
248
  puts "#{cal_name} | #{start_str} | #{end_str} | #{desc}"
@@ -210,7 +259,7 @@ module FlycalCli
210
259
  end
211
260
  end
212
261
 
213
- def print_summary(events)
262
+ def print_summary(events, time_min:, time_max:)
214
263
  total_minutes = 0
215
264
 
216
265
  events.each do |item|
@@ -227,10 +276,15 @@ module FlycalCli
227
276
 
228
277
  hours = (total_minutes / 60).floor
229
278
  mins = (total_minutes % 60).round
279
+ total_working_days = (total_minutes / 60.0 / 8).round(1)
280
+
281
+ from_str = time_min.strftime("%Y-%m-%d %H:%M")
282
+ to_str = time_max.strftime("%Y-%m-%d %H:%M")
230
283
 
231
284
  puts "\n---"
232
- puts "Eventi trovati: #{events.size}"
233
- puts "Tempo totale occupato: #{hours}h #{mins}min"
285
+ puts "From: #{from_str} | To: #{to_str}"
286
+ puts "Events found: #{events.size}"
287
+ puts "Total time occupied: #{hours}h #{mins}min (#{total_working_days} working days)"
234
288
  end
235
289
  end
236
290
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FlycalCli
4
- VERSION = "0.1.0"
4
+ VERSION = '0.2.1'
5
5
  end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flycal-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - flycal-cli
8
- bindir: exe
8
+ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
@@ -104,7 +104,7 @@ extra_rdoc_files: []
104
104
  files:
105
105
  - LICENSE
106
106
  - README.md
107
- - exe/flycal
107
+ - bin/flycal
108
108
  - lib/flycal_cli.rb
109
109
  - lib/flycal_cli/auth.rb
110
110
  - lib/flycal_cli/calendar_service.rb
File without changes