tms-remind 0.1.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4605b2629d4ad8770d867824ae7804e51d7d05665f890a3556fe451fd3fcb14a
4
+ data.tar.gz: eb12abc6ce54e1f9b4adeee84874df871194af71948df7358076dde88a843fc6
5
+ SHA512:
6
+ metadata.gz: 5e867ace940e3982d0ba3dd85752bca92f6609bc37459414481f18c79dc15823bfeb26b8d980e0c7ccc7889ad0559c501897f9f17f915c0a03f736ae5119fdcc
7
+ data.tar.gz: 4ab3295d9fab990d0032cb9de8a7068ed6eccab17704f05e8c941ffcbb01f9659f47f31e3f0c4faace72e0b1b790c88488d05f596fde7a7e9b129e1c2c5e0f7c
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # Remind
2
+
3
+ TODO: Delete this and the text below, and describe your gem
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/remind`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ ```bash
14
+ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
15
+ ```
16
+
17
+ If bundler is not being used to manage dependencies, install the gem by executing:
18
+
19
+ ```bash
20
+ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ 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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/remind.
36
+
37
+
38
+
39
+ #Example
40
+
41
+ add: bin/remind add "Học Ruby" --desc "Học lập trình Ruby" --start "2024-09-01" --end "2024-09-15" --status 'pending' --desc=DESC --end=END --start=START
42
+
43
+ list bin/remind list
44
+
45
+ remove: bin/remove 1
46
+
47
+ update: bin/remind update 2 --status 'in_progress'
48
+
49
+ get: bin/remind get 1
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ task default: %i[]
5
+ Dir.glob('lib/tasks/**/*.rake').each { |r| load r }
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ # This file is auto-generated by Thor CLI
3
+ set :output, "/home/vu/Documents/training-ruby/remind/log/cron_log.log"
4
+ set :environment, :development
5
+
6
+ every 1.hour do
7
+ rake 'remind:notify_due_tasks'
8
+ end
9
+
10
+ every 7.days do
11
+ rake 'log:clear'
12
+ end
13
+
14
+ every month do
15
+ rake 'remind:completed_tasks_last_month'
16
+ end
17
+
data/exe/remind ADDED
@@ -0,0 +1,3 @@
1
+ require 'remind'
2
+
3
+ Remind::Commands::Cli.start(ARGV)
@@ -0,0 +1,91 @@
1
+ require 'thor'
2
+ require 'fileutils'
3
+ require 'pry'
4
+
5
+ module Remind
6
+ module Commands
7
+ class Cli < Thor
8
+
9
+ SCHEDULE_FILE = File.expand_path(File.join(Dir.pwd, 'config', 'schedule.rb'))
10
+
11
+ desc "set_env", "Set SLACK_WEBHOOK_URL in .env file"
12
+ def set_env
13
+ webhook_url = ask("Enter your Slack Webhook URL:")
14
+
15
+ if webhook_url.empty?
16
+ puts 'No URL provided. Aborting...'
17
+ return
18
+ end
19
+
20
+ FileUtils.touch('.env') unless File.exist?('.env')
21
+
22
+ env_content = File.read('.env')
23
+ if env_content.match?(/^SLACK_WEBHOOK_URL=/)
24
+ env_content.gsub!(/^SLACK_WEBHOOK_URL=.*/, "SLACK_WEBHOOK_URL=#{webhook_url}")
25
+ else
26
+ env_content << "\nSLACK_WEBHOOK_URL=#{webhook_url}\n"
27
+ end
28
+
29
+ File.write('.env', env_content)
30
+ puts 'SLACK_WEBHOOK_URL has been set in .env file.'
31
+ end
32
+
33
+ desc 'add_task INTERVAL COMMAND', 'Add a task to the schedule'
34
+ def add_task(interval, command)
35
+ unless File.exist?(SCHEDULE_FILE)
36
+ create_schedule_file
37
+ end
38
+
39
+ new_task = "every #{interval} do\n rake '#{command}'\nend\n\n"
40
+ File.open(SCHEDULE_FILE, 'a') { |f| f.puts new_task }
41
+ puts "Task added to #{SCHEDULE_FILE}"
42
+ update_cron
43
+ end
44
+
45
+ desc 'create_schedule_file', 'Create a schedule file'
46
+ def create_schedule_file
47
+ FileUtils.mkdir_p(File.dirname(SCHEDULE_FILE))
48
+ File.open(SCHEDULE_FILE, 'w') do |file|
49
+ file.puts "# frozen_string_literal: true"
50
+ file.puts "# This file is auto-generated by Thor CLI"
51
+ file.puts "set :output, \"#{Dir.pwd}/log/cron_log.log\""
52
+ file.puts "set :environment, :development\n\n"
53
+ end
54
+ puts "Schedule file created at #{SCHEDULE_FILE}"
55
+ end
56
+
57
+
58
+ desc 'update_cron', 'Update cron job'
59
+ def update_cron
60
+ system("whenever --update-crontab")
61
+ puts "Crontab updated"
62
+ end
63
+
64
+ desc 'list_tasks', 'List all tasks'
65
+ def list_tasks
66
+ unless File.exist?(SCHEDULE_FILE)
67
+ create_schedule_file
68
+ end
69
+
70
+ tasks = File.readlines(SCHEDULE_FILE).select { |line| line.match?(/^every/) }
71
+
72
+ if tasks.empty?
73
+ puts "No tasks found."
74
+ else
75
+ puts "Scheduled tasks:"
76
+ tasks.each { |task| puts task }
77
+ end
78
+ end
79
+
80
+
81
+ desc 'remove_task COMMAND', 'Remove a task from the schedule'
82
+ def remove_task(command)
83
+ content = File.read(SCHEDULE_FILE)
84
+ new_content = content.gsub(/every .* do\n\s+rake '#{command}'\nend\n/, '')
85
+ File.write(SCHEDULE_FILE, new_content)
86
+ puts "Task removed from #{command}"
87
+ update_cron
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pry'
4
+ require_relative 'log_handler'
5
+ module Remind
6
+ module Helper
7
+ module ErrorHandler
8
+ include Remind::Helper::LogHandler
9
+ def handle_errors
10
+ yield
11
+ rescue StandardError => e
12
+ puts "Error: #{e.class} - #{e.message}"
13
+ # binding.pry
14
+ create_log(Logger::ERROR, e.message || 'Unknown error', 'log/log.log')
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'logger'
5
+
6
+ module Remind
7
+ module Helper
8
+ module LogHandler
9
+ def self.clear_log(filename = 'log/log.log')
10
+ File.exist?(filename) ? File.truncate(filename, 0) : return
11
+ end
12
+
13
+ def create_log(level, message, filename = 'log/log.log')
14
+ FileUtils.touch(filename) unless File.exist?(filename)
15
+ logger = Logger.new(filename, File::WRONLY | File::APPEND | File::CREAT)
16
+
17
+ logger.formatter = proc do |severity, datetime, _progname, msg|
18
+ "#{datetime.strftime('%Y-%m-%d %H:%M:%S')} - #{severity} - #{msg}\n"
19
+ end
20
+ logger.add(level, message)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'json'
5
+ require 'dotenv/load'
6
+ require 'pry'
7
+ require_relative '../helpers/error_handler'
8
+
9
+ module Remind
10
+ module Service
11
+ class Notifier
12
+ extend Remind::Helper::ErrorHandler
13
+ # Send message to slack
14
+ def self.notify(message)
15
+ handle_errors do
16
+ payload = { "text": message }.to_json
17
+ uri = URI(ENV['SLACK_WEBHOOK_URL'])
18
+ Net::HTTP.post(uri, payload, 'Content-Type' => 'application/json')
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+ require 'tms_task_manager'
5
+ require_relative 'notifier'
6
+ require_relative '../helpers/error_handler'
7
+ require_relative '../helpers/log_handler'
8
+
9
+ module Remind
10
+ module Service
11
+ class Report
12
+ extend Remind::Helper::ErrorHandler
13
+ extend Remind::Helper::LogHandler
14
+
15
+ # Notify completed tasks last month
16
+ def self.completed_tasks_last_month
17
+ handle_errors do
18
+ tasks = TmsTaskManager::Services::TaskList.list
19
+ puts tasks
20
+ current_time = Time.now
21
+ one_month_ago = current_time - (30 * 24 * 60 * 60)
22
+ messages = []
23
+ completed_tasks = tasks.select do |task|
24
+ task['status'] == 'completed' &&
25
+ Time.parse(task['end_date']) >= one_month_ago &&
26
+ Time.parse(task['end_date']) <= current_time
27
+ end
28
+
29
+ if completed_tasks.empty?
30
+ create_log(Logger::INFO, 'No completed tasks in the last month')
31
+ else
32
+ completed_tasks.each do |task|
33
+ create_log(Logger::INFO, "Task '#{task['title']}' (Completed: #{task['end_date']})")
34
+ messages << "Task '#{task['title']}' (Completed: #{task['end_date']})"
35
+ end
36
+ end
37
+
38
+ Remind::Service::Notifier.notify(messages.join("\n"))
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+ require 'pry'
5
+ require 'tms_task_manager'
6
+ require_relative 'notifier'
7
+ require_relative '../helpers/error_handler'
8
+ require_relative '../helpers/log_handler'
9
+
10
+ module Remind
11
+ module Service
12
+ class Scheduler
13
+ extend Remind::Helper::ErrorHandler
14
+ extend Remind::Helper::LogHandler
15
+
16
+ # Notify due tasks
17
+ def self.start
18
+ handle_errors do
19
+ tasks = TmsTaskManager::Services::TaskList.list
20
+ puts tasks
21
+ # binding.pry
22
+ messages = []
23
+ tasks.each do |task|
24
+ start_date = Time.parse(task['start_date'])
25
+ due_date = Time.parse(task['end_date'])
26
+ status = task['status']
27
+ task_name = task['title']
28
+
29
+ if status == 'completed'
30
+ create_log(Logger::INFO, "Task '#{task_name}' (Completed: #{due_date.strftime('%Y-%m-%d')})")
31
+ elsif Time.now < start_date
32
+ create_log(Logger::INFO, "Task '#{task_name}' (Not Started: #{start_date.strftime('%Y-%m-%d')})")
33
+ elsif Time.now <= due_date
34
+ create_log(Logger::INFO, "Task '#{task_name}' (In Progress: from #{start_date.strftime('%Y-%m-%d')} to #{due_date.strftime('%Y-%m-%d')})")
35
+ else
36
+ create_log(Logger::ERROR, "Task '#{task_name}' (Overdue: from #{start_date.strftime('%Y-%m-%d')} to #{due_date.strftime('%Y-%m-%d')})")
37
+ messages << "Task '#{task_name}' (Overdue: from #{start_date.strftime('%Y-%m-%d')} to #{due_date.strftime('%Y-%m-%d')})"
38
+ end
39
+ end
40
+
41
+ Remind::Service::Notifier.notify(messages.join("\n"))
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Remind
4
+ VERSION = '0.1.2'
5
+ end
data/lib/remind.db ADDED
Binary file
data/lib/remind.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'remind/version'
4
+ require_relative 'remind/services/scheduler'
5
+ require_relative 'remind/services/report'
6
+ require_relative 'remind/helpers/log_handler'
7
+ require_relative 'remind/commands/cli'
8
+ module Remind
9
+ class Error < StandardError; end
10
+ # Your code goes here...
11
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../remind'
4
+
5
+ namespace :log do
6
+ desc 'Clear log'
7
+ task :clear do
8
+ Remind::Helper::LogHandler.clear_log
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../remind'
4
+
5
+ namespace :remind do
6
+ desc 'Notify due tasks'
7
+ task :notify_due_tasks do
8
+ Remind::Service::Scheduler.start
9
+ end
10
+
11
+ desc 'Notify completed tasks last month'
12
+ task :completed_tasks_last_month do
13
+ Remind::Service::Report.completed_tasks_last_month
14
+ end
15
+ end
data/log/cron_log.log ADDED
@@ -0,0 +1,15 @@
1
+ Listing all tasks: [{"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}, {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}]
2
+ {"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}
3
+ {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}
4
+ Listing all tasks: [{"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}, {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}]
5
+ {"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}
6
+ {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}
7
+ Listing all tasks: [{"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}, {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}]
8
+ {"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}
9
+ {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}
10
+ Listing all tasks: [{"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}, {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}]
11
+ {"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}
12
+ {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}
13
+ Listing all tasks: [{"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}, {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}]
14
+ {"id" => 1, "title" => "Học Rails", "status" => "completed", "start_date" => "2025-03-25", "end_date" => "2025-03-26"}
15
+ {"id" => 3, "title" => "Learn Python", "status" => "pending", "start_date" => "2024-02-01", "end_date" => "2024-03-01"}
data/log/log.log ADDED
@@ -0,0 +1,17 @@
1
+ 2025-03-27 22:17:07 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
2
+ 2025-03-27 22:18:23 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
3
+ 2025-03-27 22:18:23 - ERROR - Task 'Learn Python' (Overdue: from 2024-02-01 to 2024-03-01)
4
+ 2025-03-27 22:36:05 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
5
+ 2025-03-27 22:36:05 - ERROR - Task 'Learn Python' (Overdue: from 2024-02-01 to 2024-03-01)
6
+ 2025-03-27 22:36:24 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
7
+ 2025-03-27 23:00:02 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
8
+ 2025-03-27 23:00:02 - ERROR - Task 'Learn Python' (Overdue: from 2024-02-01 to 2024-03-01)
9
+ 2025-03-28 00:04:50 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
10
+ 2025-03-28 00:04:50 - ERROR - Task 'Learn Python' (Overdue: from 2024-02-01 to 2024-03-01)
11
+ 2025-03-28 08:04:44 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
12
+ 2025-03-28 08:04:44 - ERROR - Task 'Learn Python' (Overdue: from 2024-02-01 to 2024-03-01)
13
+ 2025-03-28 08:12:02 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
14
+ 2025-03-28 08:13:01 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
15
+ 2025-03-28 08:14:02 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
16
+ 2025-03-28 08:15:02 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
17
+ 2025-03-28 08:16:02 - INFO - Task 'Học Rails' (Completed: 2025-03-26)
data/sig/remind.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Remind
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tms-remind
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - tms-nguyenvu
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 2025-03-28 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: pry
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '0.14'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.14'
26
+ - !ruby/object:Gem::Dependency
27
+ name: sqlite3
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.5'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '3.0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '1.5'
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '3.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '3.12'
53
+ type: :development
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.12'
60
+ - !ruby/object:Gem::Dependency
61
+ name: rubocop
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '1.50'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '1.50'
74
+ description: Remind is a Ruby gem that helps manage task reminders and send notifications
75
+ via Slack.
76
+ email:
77
+ - vu.nguyen1@tomosia.com
78
+ executables:
79
+ - remind
80
+ extensions: []
81
+ extra_rdoc_files: []
82
+ files:
83
+ - README.md
84
+ - Rakefile
85
+ - config/schedule.rb
86
+ - exe/remind
87
+ - lib/remind.db
88
+ - lib/remind.rb
89
+ - lib/remind/commands/cli.rb
90
+ - lib/remind/helpers/error_handler.rb
91
+ - lib/remind/helpers/log_handler.rb
92
+ - lib/remind/services/notifier.rb
93
+ - lib/remind/services/report.rb
94
+ - lib/remind/services/scheduler.rb
95
+ - lib/remind/version.rb
96
+ - lib/tasks/log.rake
97
+ - lib/tasks/remind.rake
98
+ - log/cron_log.log
99
+ - log/log.log
100
+ - sig/remind.rbs
101
+ homepage: https://github.com/tms-nguyenvu/training-ruby/tree/exercise-03/remind
102
+ licenses: []
103
+ metadata:
104
+ allowed_push_host: https://rubygems.org
105
+ homepage_uri: https://github.com/tms-nguyenvu/training-ruby/tree/exercise-03/remind
106
+ source_code_uri: https://github.com/tms-nguyenvu/training-ruby/tree/exercise-03/remind
107
+ changelog_uri: https://github.com/tms-nguyenvu/training-ruby/tree/exercise-03/remind
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: 3.1.0
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubygems_version: 3.6.2
123
+ specification_version: 4
124
+ summary: A task reminder and notification gem.
125
+ test_files: []