matterbridge 2.1.6-dev.2 → 2.1.6-dev.4

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.
@@ -1,10 +1,5 @@
1
- import { AnsiLogger, BLUE, db, er, nf, nt, rs, UNDERLINE, UNDERLINEOFF, wr } from './logger/export.js';
2
- import path from 'path';
3
- import { promises as fs } from 'fs';
4
- import { pathToFileURL } from 'url';
5
- import { exec } from 'child_process';
1
+ import { AnsiLogger, UNDERLINE, UNDERLINEOFF, BLUE, db, er, nf, nt, rs, wr } from './logger/export.js';
6
2
  import { plg, typ } from './matterbridgeTypes.js';
7
- import { shelly_config, somfytahoma_config, zigbee2mqtt_config } from './defaultConfigSchema.js';
8
3
  export class PluginManager {
9
4
  _plugins = new Map();
10
5
  nodeContext;
@@ -84,12 +79,14 @@ export class PluginManager {
84
79
  return plugins.length;
85
80
  }
86
81
  async resolve(pluginPath) {
82
+ const { default: path } = await import('node:path');
83
+ const { promises } = await import('node:fs');
87
84
  if (!pluginPath.endsWith('package.json'))
88
85
  pluginPath = path.join(pluginPath, 'package.json');
89
86
  let packageJsonPath = path.resolve(pluginPath);
90
87
  this.log.debug(`Resolving plugin path ${plg}${packageJsonPath}${db}`);
91
88
  try {
92
- await fs.access(packageJsonPath);
89
+ await promises.access(packageJsonPath);
93
90
  }
94
91
  catch {
95
92
  this.log.debug(`Package.json not found at ${plg}${packageJsonPath}${db}`);
@@ -97,7 +94,7 @@ export class PluginManager {
97
94
  this.log.debug(`Trying at ${plg}${packageJsonPath}${db}`);
98
95
  }
99
96
  try {
100
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
97
+ const packageJson = JSON.parse(await promises.readFile(packageJsonPath, 'utf8'));
101
98
  if (!packageJson.name) {
102
99
  this.log.error(`Package.json name not found at ${packageJsonPath}`);
103
100
  return null;
@@ -161,9 +158,10 @@ export class PluginManager {
161
158
  }
162
159
  }
163
160
  async parse(plugin) {
164
- this.log.debug(`Parsing package.json of plugin ${plg}${plugin.name}${db}`);
161
+ const { promises } = await import('node:fs');
165
162
  try {
166
- const packageJson = JSON.parse(await fs.readFile(plugin.path, 'utf8'));
163
+ this.log.debug(`Parsing package.json of plugin ${plg}${plugin.name}${db}`);
164
+ const packageJson = JSON.parse(await promises.readFile(plugin.path, 'utf8'));
167
165
  if (!packageJson.name)
168
166
  this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no name in package.json`);
169
167
  if (!packageJson.version)
@@ -235,6 +233,7 @@ export class PluginManager {
235
233
  }
236
234
  }
237
235
  async enable(nameOrPath) {
236
+ const { promises } = await import('node:fs');
238
237
  if (!nameOrPath || nameOrPath === '')
239
238
  return null;
240
239
  if (this._plugins.has(nameOrPath)) {
@@ -250,7 +249,7 @@ export class PluginManager {
250
249
  return null;
251
250
  }
252
251
  try {
253
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
252
+ const packageJson = JSON.parse(await promises.readFile(packageJsonPath, 'utf8'));
254
253
  const plugin = this._plugins.get(packageJson.name);
255
254
  if (!plugin) {
256
255
  this.log.error(`Failed to enable plugin ${plg}${nameOrPath}${er}: plugin not registered`);
@@ -267,6 +266,7 @@ export class PluginManager {
267
266
  }
268
267
  }
269
268
  async disable(nameOrPath) {
269
+ const { promises } = await import('node:fs');
270
270
  if (!nameOrPath || nameOrPath === '')
271
271
  return null;
272
272
  if (this._plugins.has(nameOrPath)) {
@@ -282,7 +282,7 @@ export class PluginManager {
282
282
  return null;
283
283
  }
284
284
  try {
285
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
285
+ const packageJson = JSON.parse(await promises.readFile(packageJsonPath, 'utf8'));
286
286
  const plugin = this._plugins.get(packageJson.name);
287
287
  if (!plugin) {
288
288
  this.log.error(`Failed to disable plugin ${plg}${nameOrPath}${er}: plugin not registered`);
@@ -299,6 +299,7 @@ export class PluginManager {
299
299
  }
300
300
  }
301
301
  async remove(nameOrPath) {
302
+ const { promises } = await import('node:fs');
302
303
  if (!nameOrPath || nameOrPath === '')
303
304
  return null;
304
305
  if (this._plugins.has(nameOrPath)) {
@@ -314,7 +315,7 @@ export class PluginManager {
314
315
  return null;
315
316
  }
316
317
  try {
317
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
318
+ const packageJson = JSON.parse(await promises.readFile(packageJsonPath, 'utf8'));
318
319
  const plugin = this._plugins.get(packageJson.name);
319
320
  if (!plugin) {
320
321
  this.log.error(`Failed to remove plugin ${plg}${nameOrPath}${er}: plugin not registered`);
@@ -331,6 +332,7 @@ export class PluginManager {
331
332
  }
332
333
  }
333
334
  async add(nameOrPath) {
335
+ const { promises } = await import('node:fs');
334
336
  if (!nameOrPath || nameOrPath === '')
335
337
  return null;
336
338
  const packageJsonPath = await this.resolve(nameOrPath);
@@ -339,7 +341,7 @@ export class PluginManager {
339
341
  return null;
340
342
  }
341
343
  try {
342
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
344
+ const packageJson = JSON.parse(await promises.readFile(packageJsonPath, 'utf8'));
343
345
  if (this._plugins.get(packageJson.name)) {
344
346
  this.log.info(`Plugin ${plg}${nameOrPath}${nf} already registered`);
345
347
  return null;
@@ -351,15 +353,16 @@ export class PluginManager {
351
353
  return plugin || null;
352
354
  }
353
355
  catch (err) {
354
- this.log.error(`Failed to parse package.json of plugin ${plg}${nameOrPath}${er}: ${err}`);
356
+ this.log.error(`Failed to parse package.json of plugin ${plg}${nameOrPath}${er}: ${err instanceof Error ? err.message : err}`);
355
357
  return null;
356
358
  }
357
359
  }
358
360
  async install(name) {
361
+ const { exec } = await import('node:child_process');
359
362
  await this.uninstall(name);
360
363
  this.log.info(`Installing plugin ${plg}${name}${nf}`);
361
- return new Promise((resolve, reject) => {
362
- exec(`npm install -g ${name} --omit=dev --force`, (error, stdout, stderr) => {
364
+ return new Promise((resolve) => {
365
+ exec(`npm install -g ${name} --omit=dev`, (error, stdout, stderr) => {
363
366
  if (error) {
364
367
  this.log.error(`Failed to install plugin ${plg}${name}${er}: ${error}`);
365
368
  this.log.debug(`Failed to install plugin ${plg}${name}${db}: ${stderr}`);
@@ -389,9 +392,10 @@ export class PluginManager {
389
392
  });
390
393
  }
391
394
  async uninstall(name) {
395
+ const { exec } = await import('node:child_process');
392
396
  this.log.info(`Uninstalling plugin ${plg}${name}${nf}`);
393
- return new Promise((resolve, reject) => {
394
- exec(`npm uninstall -g ${name} --force`, (error, stdout, stderr) => {
397
+ return new Promise((resolve) => {
398
+ exec(`npm uninstall -g ${name}`, (error, stdout, stderr) => {
395
399
  if (error) {
396
400
  this.log.error(`Failed to uninstall plugin ${plg}${name}${er}: ${error}`);
397
401
  this.log.debug(`Failed to uninstall plugin ${plg}${name}${db}: ${stderr}`);
@@ -406,6 +410,8 @@ export class PluginManager {
406
410
  });
407
411
  }
408
412
  async load(plugin, start = false, message = '', configure = false) {
413
+ const { promises } = await import('node:fs');
414
+ const { default: path } = await import('node:path');
409
415
  if (!plugin.enabled) {
410
416
  this.log.error(`Plugin ${plg}${plugin.name}${er} not enabled`);
411
417
  return undefined;
@@ -416,8 +422,9 @@ export class PluginManager {
416
422
  }
417
423
  this.log.info(`Loading plugin ${plg}${plugin.name}${nf} type ${typ}${plugin.type}${nf}`);
418
424
  try {
419
- const packageJson = JSON.parse(await fs.readFile(plugin.path, 'utf8'));
425
+ const packageJson = JSON.parse(await promises.readFile(plugin.path, 'utf8'));
420
426
  const pluginEntry = path.resolve(path.dirname(plugin.path), packageJson.main);
427
+ const { pathToFileURL } = await import('node:url');
421
428
  const pluginUrl = pathToFileURL(pluginEntry);
422
429
  this.log.debug(`Importing plugin ${plg}${plugin.name}${db} from ${pluginUrl.href}`);
423
430
  const pluginInstance = await import(pluginUrl.href);
@@ -463,7 +470,7 @@ export class PluginManager {
463
470
  }
464
471
  }
465
472
  catch (err) {
466
- this.log.error(`Failed to load plugin ${plg}${plugin.name}${er}: ${err}`);
473
+ this.log.error(`Failed to load plugin ${plg}${plugin.name}${er}: ${err instanceof Error ? err.message : err}`);
467
474
  plugin.error = true;
468
475
  }
469
476
  return undefined;
@@ -493,7 +500,7 @@ export class PluginManager {
493
500
  }
494
501
  catch (err) {
495
502
  plugin.error = true;
496
- this.log.error(`Failed to start plugin ${plg}${plugin.name}${er}: ${err}`);
503
+ this.log.error(`Failed to start plugin ${plg}${plugin.name}${er}: ${err instanceof Error ? err.message : err}`);
497
504
  }
498
505
  return undefined;
499
506
  }
@@ -543,7 +550,7 @@ export class PluginManager {
543
550
  this.log.debug(`Plugin ${plg}${plugin.name}${db} not configured`);
544
551
  }
545
552
  if (!plugin.platform) {
546
- this.log.debug(`*Plugin ${plg}${plugin.name}${db} no platform found`);
553
+ this.log.debug(`Plugin ${plg}${plugin.name}${db} no platform found`);
547
554
  return undefined;
548
555
  }
549
556
  this.log.info(`Shutting down plugin ${plg}${plugin.name}${nf}: ${reason}...`);
@@ -565,15 +572,18 @@ export class PluginManager {
565
572
  return plugin;
566
573
  }
567
574
  catch (err) {
568
- this.log.error(`Failed to shut down plugin ${plg}${plugin.name}${er}: ${err}`);
575
+ this.log.error(`Failed to shut down plugin ${plg}${plugin.name}${er}: ${err instanceof Error ? err.message : err}`);
569
576
  }
570
577
  return undefined;
571
578
  }
572
579
  async loadConfig(plugin) {
580
+ const { default: path } = await import('node:path');
581
+ const { promises } = await import('node:fs');
582
+ const { shelly_config, somfytahoma_config, zigbee2mqtt_config } = await import('./defaultConfigSchema.js');
573
583
  const configFile = path.join(this.matterbridge.matterbridgeDirectory, `${plugin.name}.config.json`);
574
584
  try {
575
- await fs.access(configFile);
576
- const data = await fs.readFile(configFile, 'utf8');
585
+ await promises.access(configFile);
586
+ const data = await promises.readFile(configFile, 'utf8');
577
587
  const config = JSON.parse(data);
578
588
  this.log.debug(`Loaded config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
579
589
  config.name = plugin.name;
@@ -585,45 +595,43 @@ export class PluginManager {
585
595
  return config;
586
596
  }
587
597
  catch (err) {
588
- if (err) {
589
- const nodeErr = err;
590
- if (nodeErr.code === 'ENOENT') {
591
- let config;
592
- if (plugin.name === 'matterbridge-zigbee2mqtt')
593
- config = zigbee2mqtt_config;
594
- else if (plugin.name === 'matterbridge-somfy-tahoma')
595
- config = somfytahoma_config;
596
- else if (plugin.name === 'matterbridge-shelly')
597
- config = shelly_config;
598
- else
599
- config = { name: plugin.name, type: plugin.type, debug: false, unregisterOnShutdown: false };
600
- try {
601
- await fs.writeFile(configFile, JSON.stringify(config, null, 2), 'utf8');
602
- this.log.debug(`Created config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
603
- return config;
604
- }
605
- catch (err) {
606
- this.log.error(`Error creating config file ${configFile} for plugin ${plg}${plugin.name}${er}: ${err}`);
607
- return config;
608
- }
598
+ const nodeErr = err;
599
+ if (nodeErr.code === 'ENOENT') {
600
+ let config;
601
+ if (plugin.name === 'matterbridge-zigbee2mqtt')
602
+ config = zigbee2mqtt_config;
603
+ else if (plugin.name === 'matterbridge-somfy-tahoma')
604
+ config = somfytahoma_config;
605
+ else if (plugin.name === 'matterbridge-shelly')
606
+ config = shelly_config;
607
+ else
608
+ config = { name: plugin.name, type: plugin.type, debug: false, unregisterOnShutdown: false };
609
+ try {
610
+ await promises.writeFile(configFile, JSON.stringify(config, null, 2), 'utf8');
611
+ this.log.debug(`Created config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
612
+ return config;
609
613
  }
610
- else {
611
- this.log.error(`Error accessing config file ${configFile} for plugin ${plg}${plugin.name}${er}: ${err}`);
612
- return { name: plugin.name, type: plugin.type, debug: false, unregisterOnShutdown: false };
614
+ catch (err) {
615
+ this.log.error(`Error creating config file ${configFile} for plugin ${plg}${plugin.name}${er}: ${err instanceof Error ? err.message : err}`);
616
+ return config;
613
617
  }
614
618
  }
615
- this.log.error(`Error loading config file ${configFile} for plugin ${plg}${plugin.name}${er}: ${err}`);
616
- return { name: plugin.name, type: plugin.type, debug: false, unregisterOnShutdown: false };
619
+ else {
620
+ this.log.error(`Error accessing config file ${configFile} for plugin ${plg}${plugin.name}${er}: ${err instanceof Error ? err.message : err}`);
621
+ return { name: plugin.name, type: plugin.type, debug: false, unregisterOnShutdown: false };
622
+ }
617
623
  }
618
624
  }
619
625
  async saveConfigFromPlugin(plugin) {
626
+ const { default: path } = await import('node:path');
627
+ const { promises } = await import('node:fs');
620
628
  if (!plugin.platform?.config) {
621
629
  this.log.error(`Error saving config file for plugin ${plg}${plugin.name}${er}: config not found`);
622
630
  return Promise.reject(new Error(`Error saving config file for plugin ${plg}${plugin.name}${er}: config not found`));
623
631
  }
624
632
  const configFile = path.join(this.matterbridge.matterbridgeDirectory, `${plugin.name}.config.json`);
625
633
  try {
626
- await fs.writeFile(configFile, JSON.stringify(plugin.platform.config, null, 2), 'utf8');
634
+ await promises.writeFile(configFile, JSON.stringify(plugin.platform.config, null, 2), 'utf8');
627
635
  this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}`);
628
636
  return Promise.resolve();
629
637
  }
@@ -633,13 +641,15 @@ export class PluginManager {
633
641
  }
634
642
  }
635
643
  async saveConfigFromJson(plugin, config) {
644
+ const { default: path } = await import('node:path');
645
+ const { promises } = await import('node:fs');
636
646
  if (!config.name || !config.type || config.name !== plugin.name) {
637
647
  this.log.error(`Error saving config file for plugin ${plg}${plugin.name}${er}. Wrong config data content:${rs}\n`, config);
638
648
  return;
639
649
  }
640
650
  const configFile = path.join(this.matterbridge.matterbridgeDirectory, `${plugin.name}.config.json`);
641
651
  try {
642
- await fs.writeFile(configFile, JSON.stringify(config, null, 2), 'utf8');
652
+ await promises.writeFile(configFile, JSON.stringify(config, null, 2), 'utf8');
643
653
  plugin.configJson = config;
644
654
  this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}`);
645
655
  }
@@ -649,10 +659,11 @@ export class PluginManager {
649
659
  }
650
660
  }
651
661
  async loadSchema(plugin) {
662
+ const { promises } = await import('node:fs');
652
663
  const schemaFile = plugin.path.replace('package.json', `${plugin.name}.schema.json`);
653
664
  try {
654
- await fs.access(schemaFile);
655
- const data = await fs.readFile(schemaFile, 'utf8');
665
+ await promises.access(schemaFile);
666
+ const data = await promises.readFile(schemaFile, 'utf8');
656
667
  const schema = JSON.parse(data);
657
668
  schema.title = plugin.description;
658
669
  schema.description = plugin.name + ' v. ' + plugin.version + ' by ' + plugin.author;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "files": {
3
3
  "main.css": "./static/css/main.cf25d33e.css",
4
- "main.js": "./static/js/main.a241d4f0.js",
4
+ "main.js": "./static/js/main.257513e8.js",
5
5
  "static/js/453.abd36b29.chunk.js": "./static/js/453.abd36b29.chunk.js",
6
6
  "static/media/roboto-latin-700-normal.woff2": "./static/media/roboto-latin-700-normal.4535474e1cf8598695ad.woff2",
7
7
  "static/media/roboto-latin-500-normal.woff2": "./static/media/roboto-latin-500-normal.7077203b1982951ecf76.woff2",
@@ -61,11 +61,11 @@
61
61
  "static/media/roboto-greek-ext-400-normal.woff": "./static/media/roboto-greek-ext-400-normal.16eb83b4a3b1ea994243.woff",
62
62
  "index.html": "./index.html",
63
63
  "main.cf25d33e.css.map": "./static/css/main.cf25d33e.css.map",
64
- "main.a241d4f0.js.map": "./static/js/main.a241d4f0.js.map",
64
+ "main.257513e8.js.map": "./static/js/main.257513e8.js.map",
65
65
  "453.abd36b29.chunk.js.map": "./static/js/453.abd36b29.chunk.js.map"
66
66
  },
67
67
  "entrypoints": [
68
68
  "static/css/main.cf25d33e.css",
69
- "static/js/main.a241d4f0.js"
69
+ "static/js/main.257513e8.js"
70
70
  ]
71
71
  }
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="./"><link rel="icon" href="./matterbridge 32x32.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>Matterbridge</title><link rel="manifest" href="./manifest.json"/><script defer="defer" src="./static/js/main.a241d4f0.js"></script><link href="./static/css/main.cf25d33e.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="./"><link rel="icon" href="./matterbridge 32x32.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>Matterbridge</title><link rel="manifest" href="./manifest.json"/><script defer="defer" src="./static/js/main.257513e8.js"></script><link href="./static/css/main.cf25d33e.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
@@ -0,0 +1,50 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 296.2 296.2">
2
+ <defs>
3
+ <linearGradient id="lg1" x1="16.6" y1="16.6" x2="279.6" y2="279.6" gradientUnits="userSpaceOnUse">
4
+ <stop offset="0" stop-color="#00b48d" />
5
+ <stop offset=".1" stop-color="#3faa77" />
6
+ <stop offset=".3" stop-color="#234148" />
7
+ <stop offset=".7" stop-color="#203b44" />
8
+ <stop offset=".9" stop-color="#ad2e6e" />
9
+ <stop offset="1" stop-color="#c81b74" />
10
+ </linearGradient>
11
+ <linearGradient id="lg2" x1="31.1" y1="31.1" x2="265.1" y2="265.1" gradientUnits="userSpaceOnUse">
12
+ <stop offset="0" stop-color="#00b48d" />
13
+ <stop offset=".2" stop-color="#285251" />
14
+ <stop offset=".4" stop-color="#234148" />
15
+ <stop offset=".8" stop-color="#203b44" />
16
+ <stop offset=".9" stop-color="#a8316c" />
17
+ <stop offset="1" stop-color="#c81b74" />
18
+ </linearGradient>
19
+ <linearGradient id="lg3" x1="116.2" y1="143.9" x2="139.8" y2="143.9"
20
+ gradientUnits="userSpaceOnUse">
21
+ <stop offset="0" stop-color="#8bc751" />
22
+ <stop offset="1" stop-color="#0db14b" />
23
+ </linearGradient>
24
+ <linearGradient id="lg4" x1="136.1" y1="100.8" x2="159.6" y2="100.8"
25
+ xlink:href="#lg3" />
26
+ <linearGradient id="lg5" x1="155.3" y1="143.9" x2="178.9" y2="143.9"
27
+ xlink:href="#lg3" />
28
+ <linearGradient id="lg6" x1="46.8" y1="25.7" x2="89.6" y2="74.8" gradientUnits="userSpaceOnUse">
29
+ <stop offset="0" stop-color="#b1d34a" />
30
+ <stop offset="1" stop-color="#50b848" />
31
+ </linearGradient>
32
+ </defs>
33
+ <rect width="296.2" height="296.2" rx="56.7" ry="56.7" style="fill:url(#lg1)" />
34
+ <rect x="16.3" y="16.3" width="263.6" height="263.6" rx="50.5" ry="50.5" style="fill:url(#lg2)" />
35
+ <circle cx="128" cy="143.9" r="11.8" style="fill:url(#lg3)" />
36
+ <circle cx="147.8" cy="100.8" r="11.8" style="fill:url(#lg4)" />
37
+ <path
38
+ d="m244.6 114.5.4-.5L160 33a17 17 0 0 0-24.7-.5l-86.4 83.3a15 15 0 0 0 9.2 26.9h19.3v-4.7l-13.7-12.7v-.1l83.7-80.8 84.2 81-13.9 12.8v4.5h19.5a15 15 0 0 0 7.4-28.1Z"
39
+ style="fill:url(#lg3)" />
40
+ <circle cx="167.1" cy="143.9" r="11.8" style="fill:url(#lg5)" />
41
+ <path fill="#fff" d="M219 89.3V35.5a10.5 10.5 0 1 0-21 0v33.7l21 20Z" />
42
+ <path
43
+ d="M91.4 73.3H83a37 37 0 0 0-14.5-28.4L65 50.2c.1 0 12.6 9 11.7 25.4-5.3-.4-11.2-1.9-16.3-5.3-11.8-7.8-16-23.7-11.9-46 8.7 1.5 34 7 43 22.8 4.1 7.3 4.1 16.1 0 26.2Z"
44
+ style="fill:url(#lg6)" />
45
+ <path
46
+ d="M65.9 80a49.6 49.6 0 0 0 17.8 2.2l16.6-16c1.6-8.3.5-15.7-3.3-22.4C84.6 22 47.8 17.5 46.2 17.4l-3-.4-.6 3c-3.8 18.4-5.9 50.6 23.2 60ZM48.4 24.4c8.7 1.5 34 7 43 22.8 4.1 7.3 4.1 16.1 0 26.2H83a37 37 0 0 0-14.5-28.4l-3.7 5.3c.1 0 12.6 9 11.7 25.4-5.3-.4-11.2-1.9-16.3-5.3-11.9-7.8-16-23.7-11.9-46Z"
47
+ fill="#1e5857" />
48
+ <path fill="#fff"
49
+ d="M250.5 90.5a17.4 17.4 0 1 1 0-34.8 17.4 17.4 0 0 1 0 34.8Zm0-22.7a5.4 5.4 0 0 0 0 10.7 5.3 5.3 0 0 0 0-10.7ZM258.8 148.2a15.9 15.9 0 0 0-9.6 28.5c-.8 4.2-5.4 4.6-5.4 4.6h-26v-43l13.6-13-1.8-2-82.2-79-81.2 78.3-2.5 2.6 13.7 13v42.9H53a21.5 21.5 0 1 0 11.7 15h12.6v18.8c0 7.8 6.4 14.1 14.1 14.1h29.3v14.8H64a10.6 10.6 0 0 0-17.7 8 10.6 10.6 0 0 0 17.6 8h157.6a16.3 16.3 0 1 0 0-16h-84.8V229h66.8c7.8 0 14.2-6.3 14.2-14.1v-19.2h27.6c14.3 0 17.8-12.8 18.5-16.6a15.9 15.9 0 0 0-5-30.9ZM43.7 210.8a10.3 10.3 0 1 1 0-20.6 10.3 10.3 0 0 1 0 20.6Zm192 36a5 5 0 1 1 0 10 5 5 0 0 1 0-10Zm-77-34.8h-22v-34h22v34Zm8.4-79.8c2.7 0 5.2 1 7.2 2.5v-10.4L188 137s2.6 1.3 4.6 1.3h6.7v68c0 3.2-2.6 5.7-5.7 5.7h-19v-34h1.4a7.5 7.5 0 0 0 0-15H120a7.5 7.5 0 0 0 0 15h.7v34h-19.3a5.7 5.7 0 0 1-5.7-5.6v-68.1h6.7c2 0 4.6-1.3 4.6-1.3l13.7-12.7v10.4a11.7 11.7 0 0 1 16 1.6v-13a14.9 14.9 0 0 0-25-10.8s-.1.2-.1.2l-.5.5-6.9 7H92.5l55-53.2 55.1 53.2h-11.8l-7-7c0-.2-.2-.3-.4-.5l-.2-.2a14.8 14.8 0 0 0-25 10.9v12.9c2.2-2.5 5.3-4.1 8.9-4.1Zm91.7 36.7a4.9 4.9 0 1 1 0-9.7 4.9 4.9 0 0 1 0 9.7Z" />
50
+ </svg>