Commit | Line | Data |
---|---|---|
c2c14655 | 1 | #!/usr/bin/env node |
2 | /* | |
3 | * indicator-lunar-calendar - shows lunar calendar information | |
4 | * Copyright (c) 2016 Adrian I Lam <adrianiainlam@gmail.com> | |
5 | * | |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | |
7 | * copy of this software and associated documentation files (the "Software"), | |
8 | * to deal in the Software without restriction, including without limitation | |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
10 | * and/or sell copies of the Software, and to permit persons to whom the | |
11 | * Software is furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be included in | |
14 | * all copies or substantial portions of the Software. | |
15 | * | |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | * THE AUTHOR OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
22 | * IN THE SOFTWARE. | |
23 | */ | |
24 | ||
25 | /* import dependencies */ | |
9ee99562 AIL |
26 | const gi = require('node-gtk'); |
27 | const Gtk = gi.require('Gtk', '3.0'); | |
28 | const AppIndicator3 = gi.require('AppIndicator3'); | |
c2c14655 | 29 | var CronJob = require('cron').CronJob; |
30 | var LunarCalendar = require('lunar-calendar-zh'); | |
988731c9 | 31 | var DBus = require('dbus-native'); |
c2c14655 | 32 | |
33 | /* setup indicator object */ | |
9ee99562 AIL |
34 | gi.startLoop(); |
35 | Gtk.init(); | |
c2c14655 | 36 | var indicator = AppIndicator3.Indicator.new( |
37 | "lunar-indicator", | |
9a229460 | 38 | __dirname + '/icons/鼠.svg', |
c2c14655 | 39 | AppIndicator3.IndicatorCategory.APPLICATION_STATUS |
40 | ); | |
9ee99562 | 41 | indicator.setStatus(AppIndicator3.IndicatorStatus.ACTIVE); |
c2c14655 | 42 | var menu = new Gtk.Menu(); |
43 | var item = new Gtk.MenuItem(); | |
44 | menu.append(item); | |
9ee99562 AIL |
45 | indicator.setMenu(menu); |
46 | menu.showAll(); | |
c2c14655 | 47 | |
48 | function update_indicator() { | |
49 | /* get current time at UTC+8, add 1 to date if after 23:00 (子時) */ | |
50 | var now = new Date(new Date().getTime() + 8 * 3600 * 1000); | |
51 | var hour = now.getUTCHours(); | |
52 | if(hour >= 23) { // 子時 of the next day | |
53 | now = new Date(now.getTime() + 24 * 3600 * 1000); | |
54 | } | |
55 | var year = now.getUTCFullYear(); | |
56 | var month = now.getUTCMonth() + 1; | |
57 | var day = now.getUTCDate(); | |
58 | ||
59 | /* obtain date/time in lunar calendar */ | |
60 | var lunar = LunarCalendar.solarToLunar(year, month, day); | |
61 | lunar.hour = '子丑寅卯辰巳午未申酉戌亥'[Math.floor((hour + 1) % 24 / 2)]; | |
62 | ||
63 | /* output formatting */ | |
64 | var compact_date = lunar.lunarMonthName + lunar.lunarDayName; | |
65 | var long_date = lunar.GanZhiYear + '年(' + lunar.zodiac + '年)\n' + | |
66 | lunar.lunarMonthName + lunar.lunarDayName; | |
67 | if(lunar.term) { // add solar term (節氣) to output if at solar term | |
68 | compact_date += ' ' + lunar.term; | |
69 | long_date += ' ' + lunar.term; | |
70 | } | |
71 | long_date += '\n' + lunar.hour + '時'; | |
72 | ||
73 | /* output to indicator */ | |
9ee99562 AIL |
74 | indicator.setIcon(__dirname + '/icons/' + lunar.zodiac + '.svg'); |
75 | indicator.setLabel(compact_date, ''); | |
76 | item.setLabel(long_date); | |
0bf60d57 | 77 | |
78 | console.log('Indicator updated. ' + lunar.hour + ' Time: ' + new Date()); | |
79 | /* DO NOT REMOVE THE ABOVE LINE. | |
80 | * I have no absolutely no idea why but the indicator doesn't get | |
81 | * updated if this line is removed. | |
82 | * It wasn't needed though before implementing the DBus section below. | |
83 | * So perhaps some kind of conflict between the two? | |
84 | */ | |
c2c14655 | 85 | } |
86 | ||
87 | var job = new CronJob({ | |
88 | cronTime: '0 * * * *', // every hour | |
89 | onTick: update_indicator, | |
90 | start: true | |
91 | }); | |
92 | ||
93 | update_indicator(); | |
988731c9 | 94 | |
95 | /* Detect resume from suspend and update date/time */ | |
96 | var bus = DBus.systemBus(); | |
97 | var service = bus.getService('org.freedesktop.login1'); | |
98 | service.getInterface( | |
99 | '/org/freedesktop/login1', | |
100 | 'org.freedesktop.login1.Manager', | |
101 | function(err, nm) { | |
102 | nm.addListener('PrepareForSleep', function(arg) { | |
103 | // PrepareForSleep returns false when resuming from suspend | |
104 | if(!arg) { | |
105 | job.stop(); // force cronjob to recalculate time | |
106 | job.start(); | |
107 | update_indicator(); | |
108 | } | |
109 | }); | |
110 | } | |
111 | ); | |
112 | ||
c2c14655 | 113 | Gtk.main(); |