Merge branch 'release-2.140.134' into main
[feisty_meow.git] / scripts / schedule / generate_reminders.pl
1 #!/usr/bin/perl
2
3 ##############
4 #  Name   : generate_reminders
5 #  Author : Chris Koeritz
6 ##############
7 # Copyright (c) 1989-$now By Author.  This script is free software; you can
8 # redistribute it and/or modify it under the terms of the GNU General Public
9 # License as published by the Free Software Foundation:
10 #     http://www.gnu.org/licenses/gpl.html
11 # or under the terms of the GNU Library license:
12 #     http://www.gnu.org/licenses/lgpl.html
13 # at your preference.  Those licenses describe your legal rights to this
14 # software, and no other rights or warranties apply.
15 # Please send updates for this code to: fred@gruntose.com -- Thanks, fred.
16 ##############
17
18 # Credits: thanks to 'calendar version 3' from kernighan & pike for good approaches.
19
20 # Note: the calendar format is like so in calendar.dat:
21 #
22 # Apr 24 Saint Shanty's Day
23 # Jul 8 Normality Day
24 # Oct 24 1985 Saint Splivven's Day
25 #
26 # Month names must currently be three letters and must be capitalized.
27 # The day must be a number, followed by a space.  An optional 4 digit
28 # year can be included.  Anything after that is considered to be the
29 # description of the event.
30
31 use Env qw(CLOUD_BASE TMP);
32
33 ##############
34
35 # all the date alerts go into this temp file.
36 local($TEMPO_FILE) = `mktemp "$TMP/zz_reminder.XXXXXX"`;
37 chop($TEMPO_FILE);
38
39 local($USER_NAME) = "$REPLYTO";
40 if (! $USER_NAME) { $USER_NAME="fred" }
41
42 #print "TEMPO is $TEMPO_FILE ; USER is $USER_NAME ; \n";
43
44 local($CAL_FILE);
45 if (! $CAL_FILE) {
46 #  print "the CAL_FILE variable is not set.\n";
47 #  print "defaulting it to a value that probably does not suit you.\n";
48   $CAL_FILE = "$CLOUD_BASE/magic_cabinet/lists/calendar.dat";
49 }
50
51 #print "calfile is $CAL_FILE\n";
52
53 # we open this really early on, to check if it exists.  we use it way down below.
54 open(DATES, "<$CAL_FILE") || die("failed to open $CAL_FILE");
55
56 ##############
57
58 # the big block here computes the list of days near today, so we can check the
59 # entries in the file.
60
61 local($MONTH_DAYS) = "Jan 31 Feb 28 Mar 31 Apr 30 May 31 Jun 30 Jul 31 Aug 31 Sep 30 Oct 31 Nov 30 Dec 31 Jan 31";
62   # we repeat january so we can wrap around into the future year.
63
64 local(@moon_data) = split(' ', $MONTH_DAYS);
65
66 #print "got moondays of @moon_data\n";
67
68 local $i, %days_in_month, %next_month;
69
70 for ($i = 0; $i < 24; $i += 2) {
71   $days_in_month{@moon_data[$i]} = $moon_data[$i + 1];
72 #print "new day=$moon_data[$i + 1]\n";
73   $next_month{@moon_data[$i]} = $moon_data[$i + 2];
74 #print "new mon=$moon_data[$i + 2]\n";
75 }
76
77 #local(@days) = %days_in_month;
78 #local(@next_month) = %next_month;
79 #print "got days wik @days\n";
80 #print "got next mon wik @next_month\n";
81
82 local(@date_as_array) = split(' ', `date '+%a %b %d %Y'`);
83 #print( "date as array: @date_as_array\n");
84
85 ##############
86
87 # now we construct the nearby dates that we care about...
88
89 local @checking_dates;
90
91 # push the pair of month and date into our list of dates to be checked.
92 push(@checking_dates, ($date_as_array[1], $date_as_array[2]));
93
94 local @pair, @new_pair;
95
96 @pair = ($checking_dates[0], $checking_dates[1]);
97 #print "got a pair @pair\n";
98
99 # add one day at a time to make sure we report if we're close enough to an event that happens
100 # tomorrow or a couple days from now, etc.
101 for ($i = 1; $i <= 7; $i++) {
102   $pair[1] = $pair[1] + 1;  # increment the day entry by one.
103   @new_pair = &fix_date_for_rollover(@pair);  # fix for rollovers.
104   push(@checking_dates, ($new_pair[0], $new_pair[1]));  # add to the checking list.
105 }
106
107 # add a few days to jump into the future to check every other day for an impending event.
108 for ($i = 1; $i <= 4; $i++) {
109   $pair[1] = $pair[1] + 2;  # increment the day entry by two days.
110   @new_pair = &fix_date_for_rollover(@pair);  # fix for rollovers.
111   push(@checking_dates, ($new_pair[0], $new_pair[1]));  # add to the checking list.
112 }
113
114 # now look a couple weeks forward also (for a total of about 3 weeks total coverage).
115 for ($i = 0; $i < 2; $i++) {
116   $pair[1] = $pair[1] + 7;  # increment the day entry by a week.
117   @new_pair = &fix_date_for_rollover(@pair);  # fix for rollovers.
118   push(@checking_dates, ($new_pair[0], $new_pair[1]));  # add to the checking list.
119 }
120
121 ##############
122
123 # finally we can test the dates in the file and see if they're getting close enough to report on.
124
125 #print "got nearby dates to check: @checking_dates\n";
126
127 while (<DATES>) {
128   local($line) = $_;
129   chop($line);
130   if (length($line) <= 0) { next; }
131 #print "line to check: '$line'\n";
132   local(@test_date) = split(' ', $line);
133   &test_date_for_proximity($test_date[0], $test_date[1], $line);
134 }
135
136 # send mail here if there's anything to say.
137 if (! -z $TEMPO_FILE) {
138   # there are some alerts in there.
139 #print "will run: system(\"mail -s \"FredMinder: \$(head -1 $TEMPO_FILE)\" $USER_NAME <$TEMPO_FILE\");\n";
140   system("mail -s \"FredMinder: \$(head -1 $TEMPO_FILE)\" $USER_NAME <$TEMPO_FILE");
141 }
142
143 unlink $TEMPO_FILE;
144
145 exit 0;
146
147 ##############
148
149 # prints the contents of the first parameter's file out to stdout.
150 sub fix_date_for_rollover {
151   local($month) = @_[0];
152   local($day) = @_[1];
153 #print "fix mon=$month day=$day\n";
154   if ($day > $days_in_month{$month}) {
155     $day = $day % $days_in_month{$month};
156     $month = $next_month{$month};
157   }
158 #print "now mon=$month day=$day\n";
159   return ($month, $day);
160 }
161
162 sub test_date_for_proximity {
163   local($month) = @_[0];
164   local($day) = @_[1];
165   local($line) = @_[2];
166 #print "test mon=$month day=$day\n";
167
168   for ($i = 0; $i < @checking_dates; $i += 2) {
169 #    print "i is $i\n";
170     local($checkmo) = lc $checking_dates[$i];
171     local($checkda) = $checking_dates[$i + 1];
172 #print "checking mon=$checkmo day=$checkda\n";
173     if ( (lc $month eq $checkmo) && ($day eq $checkda) ) {
174       # found a day that's close enough to match; send an alert about it.
175 #print "matching found!  mon=$month day=$day\n";
176       open(OUTY, ">>$TEMPO_FILE") || die("failed to open $TEMPO_FILE");
177       print OUTY $line . "\n";
178       close(OUTY);
179     }
180   }
181 }
182