+6
config/config.example.json5
+6
config/config.example.json5
+3
-1
src/index.ts
+3
-1
src/index.ts
···
4
import Sequencer from './sequencer.js';
5
import type {Programs, Segments, Sequences} from './sequencer.js';
6
import type { Voices } from './voice.js';
7
8
9
interface Config {
10
programs: Programs,
11
segments: Segments,
12
sequences: Sequences,
13
-
voices: Voices
14
}
15
16
console.log('morning-report\nCory Sanin 2025\n');
···
4
import Sequencer from './sequencer.js';
5
import type {Programs, Segments, Sequences} from './sequencer.js';
6
import type { Voices } from './voice.js';
7
+
import type { WeatherConfig } from './weather.js';
8
9
10
interface Config {
11
programs: Programs,
12
segments: Segments,
13
sequences: Sequences,
14
+
voices: Voices,
15
+
weather: WeatherConfig
16
}
17
18
console.log('morning-report\nCory Sanin 2025\n');
+101
src/weather.ts
+101
src/weather.ts
···
···
1
+
import OpenWeatherMap from 'openweathermap-ts';
2
+
import type { ThreeHourResponse, CurrentResponse, CountryCode } from 'openweathermap-ts/dist/types/index.js';
3
+
4
+
interface CityName {
5
+
cityName: string;
6
+
state: string;
7
+
countryCode: CountryCode;
8
+
}
9
+
10
+
interface WeatherConfig {
11
+
key: string;
12
+
lang?: string;
13
+
coordinates?: number[] | string;
14
+
zip?: number;
15
+
country?: CountryCode;
16
+
cityid?: number;
17
+
city?: CityName;
18
+
}
19
+
20
+
type LocationType = 'coordinates' | 'zip' | 'cityid' | 'city' | null;
21
+
22
+
function parseCoords(coords: number[] | string): number[] {
23
+
if (typeof coords == 'string') {
24
+
return coords.replace(/\s/g, '').split(',').map(Number.parseFloat);
25
+
}
26
+
return coords;
27
+
}
28
+
29
+
30
+
class Weather {
31
+
private openWeather: OpenWeatherMap.default;
32
+
private locationType: LocationType;
33
+
private current: CurrentResponse;
34
+
private threeDay: ThreeHourResponse;
35
+
36
+
constructor(options: WeatherConfig) {
37
+
this.locationType = this.current = this.threeDay = null;
38
+
this.openWeather = new OpenWeatherMap.default({
39
+
apiKey: options.key
40
+
});
41
+
if ('city' in options && 'cityName' in options.city && 'state' in options.city && 'countryCode' in options.city) {
42
+
this.openWeather.setCityName(options.city);
43
+
this.locationType = 'city';
44
+
}
45
+
if ('cityid' in options) {
46
+
this.openWeather.setCityId(options.cityid);
47
+
this.locationType = 'cityid';
48
+
}
49
+
if ('zip' in options && 'country' in options) {
50
+
this.openWeather.setZipCode(options.zip, options.country)
51
+
this.locationType = 'zip';
52
+
}
53
+
if ('coordinates' in options) {
54
+
const coords = parseCoords(options.coordinates);
55
+
if (coords.length >= 2) {
56
+
this.openWeather.setGeoCoordinates(coords[0], coords[1]);
57
+
this.locationType = 'coordinates';
58
+
}
59
+
}
60
+
}
61
+
62
+
async getCurrentWeather(): Promise<CurrentResponse> {
63
+
if (this.current) {
64
+
return this.current;
65
+
}
66
+
switch (this.locationType) {
67
+
case 'city':
68
+
return this.current = await this.openWeather.getCurrentWeatherByCityName();
69
+
case 'cityid':
70
+
return this.current = await this.openWeather.getCurrentWeatherByCityId();
71
+
case 'zip':
72
+
return this.current = await this.openWeather.getCurrentWeatherByZipcode();
73
+
case 'coordinates':
74
+
return this.current = await this.openWeather.getCurrentWeatherByGeoCoordinates();
75
+
default:
76
+
throw new Error(`Can't fetch weather for location type '${this.locationType}'`);
77
+
}
78
+
}
79
+
80
+
async getThreeHourForecast(): Promise<ThreeHourResponse> {
81
+
if (this.threeDay) {
82
+
return this.threeDay;
83
+
}
84
+
switch (this.locationType) {
85
+
case 'city':
86
+
return this.threeDay = await this.openWeather.getThreeHourForecastByCityName();
87
+
case 'cityid':
88
+
return this.threeDay = await this.openWeather.getThreeHourForecastByCityId();
89
+
case 'zip':
90
+
return this.threeDay = await this.openWeather.getThreeHourForecastByZipcode();
91
+
case 'coordinates':
92
+
return this.threeDay = await this.openWeather.getThreeHourForecastByGeoCoordinates();
93
+
default:
94
+
throw new Error(`Can't fetch weather for location type '${this.locationType}'`);
95
+
}
96
+
}
97
+
}
98
+
99
+
export default Weather;
100
+
export { Weather };
101
+
export type { WeatherConfig, CityName };