diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7fe62971..22aa51ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,8 +2,24 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## [2.1.2] - Unreleased
-## [2.1.1] - Unreleased
+### Changed
+- Fix the dockerfile to have it running from the first time.
+
+### Added
+- Add in option to wrap long calendar events to multiple lines using `wrapEvents` configuration option.
+- Add test e2e `show title newsfeed` for newsfeed module.
+- Add task to check configuration file.
+
+### Updated
+- Added missing keys to Polish translation.
+- Added missing key to German translation.
+
+### Fixed
+- Fix instruction in README for using automatically installer script.
+
+## [2.1.1] - 2017-04-01
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
@@ -23,13 +39,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Restructured Test Suite
### Added
-- Added Docker support (Pull Request [#673](https://github.com/MichMich/MagicMirror/pull/673))
-- Calendar-specific support for `maximumEntries`, and ` maximumNumberOfDays`
+- Added Docker support (Pull Request [#673](https://github.com/MichMich/MagicMirror/pull/673)).
+- Calendar-specific support for `maximumEntries`, and ` maximumNumberOfDays`.
- Add loaded function to modules, providing an async callback.
- Made default newsfeed module aware of gesture events from [MMM-Gestures](https://github.com/thobach/MMM-Gestures)
-- Add use pm2 for manager process into Installer RaspberryPi script
-- Russian Translation
-- Afrikaans Translation
+- Add use pm2 for manager process into Installer RaspberryPi script.
+- Russian Translation.
+- Afrikaans Translation.
- Add postinstall script to notify user that MagicMirror installed successfully despite warnings from NPM.
- Init tests using mocha.
- Option to use RegExp in Calendar's titleReplace.
@@ -37,24 +53,32 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Icelandic Translation.
- Add use a script to prevent when is run by SSH session set DISPLAY enviroment.
- Enable ability to set configuration file by the enviroment variable called MM_CONFIG_FILE.
-- Option to give each calendar a different color
-- Option for colored min-temp and max-temp
-- Add test e2e helloworld
-- Add test e2e enviroment
-- Add `chai-as-promised` npm module to devDependencies
-- Basic set of tests for clock module
-- Run e2e test in Travis
+- Option to give each calendar a different color.
+- Option for colored min-temp and max-temp.
+- Add test e2e helloworld.
+- Add test e2e enviroment.
+- Add `chai-as-promised` npm module to devDependencies.
+- Basic set of tests for clock module.
+- Run e2e test in Travis.
- Estonian Translation.
-- Add test for compliments module for parts of day
+- Add test for compliments module for parts of day.
- Korean Translation.
-- Added console warning on startup when deprecated config options are used
-- Add option to display temperature unit label to the current weather module
-- Added ability to disable wrapping of news items
+- Added console warning on startup when deprecated config options are used.
+- Add option to display temperature unit label to the current weather module.
+- Added ability to disable wrapping of news items.
- Added in the ability to hide events in the calendar module based on simple string filters.
- Updated Norwegian translation.
-- Added hideLoading option for News Feed module
+- Added hideLoading option for News Feed module.
- Added configurable dateFormat to clock module.
- Added multiple calendar icon support.
+- Added tests for Translations, dev argument, version, dev console.
+- Added test anytime feature compliments module.
+- Added test ipwhitelist configuration directive.
+- Added test for calendar module: default, basic-auth, backward compability, fail-basic-auth.
+- Added meta tags to support fullscreen mode on iOS (for server mode)
+- Added `ignoreOldItems` and `ignoreOlderThan` options to the News Feed module
+- Added test for MM_PORT enviroment variable.
+- Added a configurable Week section to the clock module.
### Fixed
- Update .gitignore to not ignore default modules folder.
@@ -63,8 +87,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Fix an issue where the analog clock looked scrambled. ([#611](https://github.com/MichMich/MagicMirror/issues/611))
- If units is set to imperial, the showRainAmount option of weatherforecast will show the correct unit.
- Module currentWeather: check if temperature received from api is defined.
-- Fix an issue with module hidden status changing to `true` although lock string prevented showing it
+- Fix an issue with module hidden status changing to `true` although lock string prevented showing it.
- Fix newsfeed module bug (removeStartTags)
+- Fix when is set MM_PORT enviroment variable.
- Fixed missing animation on `this.show(speed)` when module is alone in a region.
## [2.1.0] - 2016-12-31
diff --git a/Dockerfile b/Dockerfile
index ddf6d9d6..32939f95 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,19 +1,22 @@
FROM node:latest
-RUN apt-get update && apt-get -y install dos2unix
-
+ENV NODE_ENV production
+ENV MM_PORT 8080
WORKDIR /opt/magic_mirror
+
COPY . .
COPY /modules unmount_modules
COPY /config unmount_config
-ENV NODE_ENV production
-ENV MM_PORT 8080
-
-RUN npm install
-
-RUN ["dos2unix", "docker-entrypoint.sh"]
-RUN ["chmod", "+x", "docker-entrypoint.sh"]
+RUN apt-get update \
+ && apt-get -qy install tofrodos dos2unix \
+ && chmod -R 777 vendor \
+ && npm install \
+ && cd vendor \
+ && npm install \
+ && cd .. \
+ && dos2unix docker-entrypoint.sh \
+ && chmod +x docker-entrypoint.sh
EXPOSE $MM_PORT
ENTRYPOINT ["/opt/magic_mirror/docker-entrypoint.sh"]
diff --git a/Gruntfile.js b/Gruntfile.js
index 06fed2d5..8d069c82 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -6,12 +6,20 @@ module.exports = function(grunt) {
options: {
configFile: ".eslintrc.json"
},
- target: ["js/*.js", "modules/default/*.js", "modules/default/*/*.js",
- "serveronly/*.js", "*.js", "tests/*/*.js", "!modules/default/alert/notificationFx.js",
- "!modules/default/alert/modernizr.custom.js", "!modules/default/alert/classie.js",
+ target: [
+ "js/*.js",
+ "modules/default/*.js",
+ "modules/default/*/*.js",
+ "serveronly/*.js",
+ "*.js",
+ "tests/**/*.js",
+ "!modules/default/alert/notificationFx.js",
+ "!modules/default/alert/modernizr.custom.js",
+ "!modules/default/alert/classie.js",
"config/*",
- "translations/translations.js", "vendor/vendor.js"
-
+ "translations/translations.js",
+ "vendor/vendor.js",
+ "modules/node_modules/node_helper/index.js"
]
},
stylelint: {
@@ -19,14 +27,26 @@ module.exports = function(grunt) {
options: {
configFile: ".stylelintrc"
},
- src: ["css/main.css", "modules/default/calendar/calendar.css", "modules/default/clock/clock_styles.css", "modules/default/currentweather/currentweather.css", "modules/default/weatherforcast/weatherforcast.css"]
+ src: [
+ "css/main.css",
+ "modules/default/calendar/calendar.css",
+ "modules/default/clock/clock_styles.css",
+ "modules/default/currentweather/currentweather.css",
+ "modules/default/weatherforcast/weatherforcast.css"
+ ]
}
},
jsonlint: {
main: {
- src: ["package.json", ".eslintrc.json", ".stylelintrc", "translations/*.json",
- "modules/default/*/translations/*.json", "installers/pm2_MagicMirror.json",
- "vendor/package.js"],
+ src: [
+ "package.json",
+ ".eslintrc.json",
+ ".stylelintrc",
+ "translations/*.json",
+ "modules/default/*/translations/*.json",
+ "installers/pm2_MagicMirror.json",
+ "vendor/package.js"
+ ],
options: {
reporter: "jshint"
}
@@ -58,11 +78,20 @@ module.exports = function(grunt) {
"MD038": false
}
},
- src: ["README.md", "CHANGELOG.md", "LICENSE.md", "modules/README.md", "modules/default/**/*.md", "!modules/default/calendar/vendor/ical.js/readme.md"]
+ src: [
+ "README.md",
+ "CHANGELOG.md",
+ "LICENSE.md",
+ "modules/README.md",
+ "modules/default/**/*.md",
+ "!modules/default/calendar/vendor/ical.js/readme.md"
+ ]
}
},
yamllint: {
- all: [".travis.yml"]
+ all: [
+ ".travis.yml"
+ ]
}
});
grunt.loadNpmTasks("grunt-eslint");
diff --git a/README.md b/README.md
index 98ca4154..4fd480bf 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ Electron, the app wrapper around MagicMirror², only supports the Raspberry Pi 2
Execute the following command on your Raspberry Pi to install MagicMirror²:
````
-curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installers/raspberry.sh | bash
+bash -c "$(curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installers/raspberry.sh)"
````
### Manual Installation
@@ -104,6 +104,11 @@ Type `git status` to see your changes, if there are any, you can reset them with
1. Duplicate `config/config.js.sample` to `config/config.js`. **Note:** If you used the installer script. This step is already done for you.
2. Modify your required settings.
+Note: You'll can check your configuration running the follow command:
+```bash
+npm run config:check
+```
+
The following properties can be configured:
| **Option** | **Description** |
diff --git a/config/config.js.sample b/config/config.js.sample
index 53677cfa..b2eeee8a 100644
--- a/config/config.js.sample
+++ b/config/config.js.sample
@@ -2,11 +2,19 @@
*
* By Michael Teeuw http://michaelteeuw.nl
* MIT Licensed.
+ *
+ * For more information how you can configurate this file
+ * See https://github.com/MichMich/MagicMirror#configuration
+ *
*/
var config = {
port: 8080,
- ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], // Set [] to allow all IP addresses.
+ ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], // Set [] to allow all IP addresses
+ // or add a specific IPv4 of 192.168.1.5 :
+ // ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.1.5"],
+ // or IPv4 range of 192.168.3.0 --> 192.168.3.15 use CIDR format :
+ // ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.3.0/28"],
language: "en",
timeFormat: 24,
diff --git a/css/main.css b/css/main.css
index 01d40aec..49bfe611 100644
--- a/css/main.css
+++ b/css/main.css
@@ -1,6 +1,7 @@
html {
cursor: none;
overflow: hidden;
+ background: #000;
}
::-webkit-scrollbar {
diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh
index 9d91492f..5d37b4a6 100644
--- a/docker-entrypoint.sh
+++ b/docker-entrypoint.sh
@@ -5,7 +5,7 @@ if [ ! -f /opt/magic_mirror/modules ]; then
fi
if [ ! -f /opt/magic_mirror/config ]; then
- cp -R /opt/magic_mirror/unmount_config/. /opt/magic_mirror/config
+ cp -Rn /opt/magic_mirror/unmount_config/. /opt/magic_mirror/config
fi
node serveronly
diff --git a/index.html b/index.html
index 606f5aac..85951a85 100644
--- a/index.html
+++ b/index.html
@@ -4,6 +4,12 @@
Magic Mirror
+
+
+
+
+
+
diff --git a/installers/raspberry.sh b/installers/raspberry.sh
index 2df89a5f..a76c1a9e 100644
--- a/installers/raspberry.sh
+++ b/installers/raspberry.sh
@@ -65,7 +65,7 @@ if command_exists node; then
fi
else
- echo -e "\e[92mNo Node.js upgrade nessecery.\e[0m"
+ echo -e "\e[92mNo Node.js upgrade necessary.\e[0m"
fi
else
diff --git a/js/server.js b/js/server.js
index beb8b84c..36ebf740 100644
--- a/js/server.js
+++ b/js/server.js
@@ -15,9 +15,16 @@ var fs = require("fs");
var helmet = require("helmet");
var Server = function(config, callback) {
- console.log("Starting server op port " + config.port + " ... ");
+ console.log("Starting server on port " + config.port + " ... ");
- server.listen(config.port, config.address ? config.address : null);
+ var port = config.port;
+ if (process.env.MM_PORT) {
+ port = process.env.MM_PORT;
+ }
+
+ console.log("Starting server op port " + port + " ... ");
+
+ server.listen(port, config.address ? config.address : null);
if (config.ipWhitelist instanceof Array && config.ipWhitelist.length == 0) {
console.info("You're using a full whitelist configuration to allow for all IPs")
diff --git a/js/utils.js b/js/utils.js
index 76eb2703..3f623499 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -11,7 +11,8 @@ var colors = require("colors/safe");
var Utils = {
colors: {
warn: colors.yellow,
- error: colors.red
+ error: colors.red,
+ info: colors.blue
}
};
diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md
index 470560ba..003c13e1 100644
--- a/modules/default/calendar/README.md
+++ b/modules/default/calendar/README.md
@@ -31,6 +31,7 @@ The following properties can be configured:
| `displaySymbol` | Display a symbol in front of an entry.
**Possible values:** `true` or `false` **Default value:** `true`
| `defaultSymbol` | The default symbol.
**Possible values:** See [Font Awsome](http://fontawesome.io/icons/) website. **Default value:** `calendar`
| `maxTitleLength` | The maximum title length.
**Possible values:** `10` - `50` **Default value:** `25`
+| `wrapEvents` | Wrap event titles to multiple lines. Breaks lines at the length defined by `maxTitleLength`.
**Possible values:** `true` or `false` **Default value:** `false`
| `fetchInterval` | How often does the content needs to be fetched? (Milliseconds)
**Possible values:** `1000` - `86400000` **Default value:** `300000` (5 minutes)
| `animationSpeed` | Speed of the update animation. (Milliseconds)
**Possible values:**`0` - `5000` **Default value:** `2000` (2 seconds)
| `fade` | Fade the future events to black. (Gradient)
**Possible values:** `true` or `false` **Default value:** `true`
diff --git a/modules/default/calendar/calendar.css b/modules/default/calendar/calendar.css
index 26b1e93d..6bc5762d 100644
--- a/modules/default/calendar/calendar.css
+++ b/modules/default/calendar/calendar.css
@@ -2,6 +2,7 @@
padding-left: 0;
padding-right: 10px;
font-size: 80%;
+ vertical-align: top;
}
.calendar .symbol span {
@@ -19,4 +20,5 @@
.calendar .time {
padding-left: 30px;
text-align: right;
+ vertical-align: top;
}
diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js
index d2e64cc7..fa77c94a 100644
--- a/modules/default/calendar/calendar.js
+++ b/modules/default/calendar/calendar.js
@@ -18,6 +18,7 @@ Module.register("calendar", {
displayRepeatingCountTitle: false,
defaultRepeatingCountTitle: "",
maxTitleLength: 25,
+ wrapEvents: false, // wrap events to multiple lines breaking at maxTitleLength
fetchInterval: 5 * 60 * 1000, // Update every 5 minutes.
animationSpeed: 2000,
fade: true,
@@ -54,8 +55,8 @@ Module.register("calendar", {
// Define required translations.
getTranslations: function () {
- // The translations for the defaut modules are defined in the core translation files.
- // Therefor we can just return false. Otherwise we should have returned a dictionairy.
+ // The translations for the default modules are defined in the core translation files.
+ // Therefor we can just return false. Otherwise we should have returned a dictionary.
// If you're trying to build your own module including translations, check out the documentation.
return false;
},
@@ -409,20 +410,43 @@ Module.register("calendar", {
},
/* shorten(string, maxLength)
- * Shortens a string if it's longer than maxLenthg.
+ * Shortens a string if it's longer than maxLength.
* Adds an ellipsis to the end.
*
* argument string string - The string to shorten.
- * argument maxLength number - The max lenth of the string.
+ * argument maxLength number - The max length of the string.
+ * argument wrapEvents - Wrap the text after the line has reached maxLength
*
* return string - The shortened string.
*/
- shorten: function (string, maxLength) {
- if (string.length > maxLength) {
- return string.slice(0, maxLength) + "…";
- }
+ shorten: function (string, maxLength, wrapEvents) {
+ if (wrapEvents) {
+ var temp = "";
+ var currentLine = "";
+ var words = string.split(" ");
- return string;
+ for (var i = 0; i < words.length; i++) {
+ var word = words[i];
+ if (currentLine.length + word.length < 25 - 1) { // max - 1 to account for a space
+ currentLine += (word + " ");
+ } else {
+ if (currentLine.length > 0) {
+ temp += (currentLine + " " + word + " ");
+ } else {
+ temp += (word + " ");
+ }
+ currentLine = "";
+ }
+ }
+
+ return temp + currentLine;
+ } else {
+ if (string.length > maxLength) {
+ return string.slice(0, maxLength) + "…";
+ } else {
+ return string;
+ }
+ }
},
/* capFirst(string)
@@ -437,7 +461,7 @@ Module.register("calendar", {
/* titleTransform(title)
* Transforms the title of an event for usage.
* Replaces parts of the text as defined in config.titleReplace.
- * Shortens title based on config.maxTitleLength
+ * Shortens title based on config.maxTitleLength and config.wrapEvents
*
* argument title string - The title to transform.
*
@@ -456,7 +480,7 @@ Module.register("calendar", {
title = title.replace(needle, replacement);
}
- title = this.shorten(title, this.config.maxTitleLength);
+ title = this.shorten(title, this.config.maxTitleLength, this.config.wrapEvents);
return title;
},
diff --git a/modules/default/clock/README.md b/modules/default/clock/README.md
index f518a2b2..a231d73c 100644
--- a/modules/default/clock/README.md
+++ b/modules/default/clock/README.md
@@ -30,6 +30,7 @@ The following properties can be configured:
| `showPeriodUpper` | Show the period (AM/PM) with 12 hour format as uppercase.
**Possible values:** `true` or `false` **Default value:** `false`
| `clockBold` | Remove the colon and bold the minutes to make a more modern look.
**Possible values:** `true` or `false` **Default value:** `false`
| `showDate` | Turn off or on the Date section.
**Possible values:** `true` or `false` **Default value:** `true`
+| `showWeek` | Turn off or on the Week section.
**Possible values:** `true` or `false` **Default value:** `false`
| `dateFormat` | Configure the date format as you like.
**Possible values:** [Docs](http://momentjs.com/docs/#/displaying/format/) **Default value:** `"dddd, LL"`
| `displayType` | Display a digital clock, analog clock, or both together.
**Possible values:** `digital`, `analog`, or `both` **Default value:** `digital`
| `analogSize` | **Specific to the analog clock.** Defines how large the analog display is.
**Possible values:** A positive number of pixels` **Default value:** `200px`
@@ -37,4 +38,4 @@ The following properties can be configured:
| `secondsColor` | **Specific to the analog clock.** Specifies what color to make the 'seconds' hand.
**Possible values:** `any HTML RGB Color` **Default value:** `#888888`
| `analogPlacement` | **Specific to the analog clock. _(requires displayType set to `'both'`)_** Specifies where the analog clock is in relation to the digital clock
**Possible values:** `top`, `right`, `bottom`, or `left` **Default value:** `bottom`
| `analogShowDate` | **Specific to the analog clock.** If the clock is used as a separate module and set to analog only, this configures whether a date is also displayed with the clock.
**Possible values:** `false`, `top`, or `bottom` **Default value:** `top`
-| `timezone` | Specific a timezone to show clock.
**Possible examples values:** `America/New_York`, `America/Santiago`, `Etc/GMT+10` **Default value:** `none`
+| `timezone` | Specific a timezone to show clock.
**Possible examples values:** `America/New_York`, `America/Santiago`, `Etc/GMT+10` **Default value:** `none`. See more informations about configuration value [here](https://momentjs.com/timezone/docs/#/data-formats/packed-format/)
diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js
index 21e665e7..761f3948 100644
--- a/modules/default/clock/clock.js
+++ b/modules/default/clock/clock.js
@@ -16,6 +16,7 @@ Module.register("clock",{
showPeriodUpper: false,
clockBold: false,
showDate: true,
+ showWeek: false,
dateFormat: "dddd, LL",
/* specific to the analog clock */
@@ -61,10 +62,12 @@ Module.register("clock",{
var timeWrapper = document.createElement("div");
var secondsWrapper = document.createElement("sup");
var periodWrapper = document.createElement("span");
+ var weekWrapper = document.createElement("div")
// Style Wrappers
dateWrapper.className = "date normal medium";
timeWrapper.className = "time bright large light";
secondsWrapper.className = "dimmed";
+ weekWrapper.className = "week dimmed medium"
// Set content of wrappers.
// The moment().format("h") method has a bug on the Raspberry Pi.
@@ -90,6 +93,9 @@ Module.register("clock",{
if(this.config.showDate){
dateWrapper.innerHTML = now.format(this.config.dateFormat);
}
+ if (this.config.showWeek) {
+ weekWrapper.innerHTML = this.translate("WEEK") + " " + now.week();
+ }
timeWrapper.innerHTML = timeString;
secondsWrapper.innerHTML = now.format("ss");
if (this.config.showPeriodUpper) {
@@ -172,16 +178,25 @@ Module.register("clock",{
// Display only a digital clock
wrapper.appendChild(dateWrapper);
wrapper.appendChild(timeWrapper);
+ wrapper.appendChild(weekWrapper);
} else if (this.config.displayType === "analog") {
// Display only an analog clock
dateWrapper.style.textAlign = "center";
- dateWrapper.style.paddingBottom = "15px";
+
+ if (this.config.showWeek) {
+ weekWrapper.style.paddingBottom = "15px";
+ } else {
+ dateWrapper.style.paddingBottom = "15px";
+ }
+
if (this.config.analogShowDate === "top") {
wrapper.appendChild(dateWrapper);
+ wrapper.appendChild(weekWrapper);
wrapper.appendChild(clockCircle);
} else if (this.config.analogShowDate === "bottom") {
wrapper.appendChild(clockCircle);
wrapper.appendChild(dateWrapper);
+ wrapper.appendChild(weekWrapper);
} else {
wrapper.appendChild(clockCircle);
}
@@ -198,6 +213,7 @@ Module.register("clock",{
digitalWrapper.style.cssFloat = "none";
digitalWrapper.appendChild(dateWrapper);
digitalWrapper.appendChild(timeWrapper);
+ digitalWrapper.appendChild(weekWrapper);
var appendClocks = function(condition, pos1, pos2) {
var padding = [0,0,0,0];
diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js
index 1b55e255..6e23cdcf 100644
--- a/modules/default/currentweather/currentweather.js
+++ b/modules/default/currentweather/currentweather.js
@@ -79,8 +79,8 @@ Module.register("currentweather",{
// Define required translations.
getTranslations: function() {
- // The translations for the defaut modules are defined in the core translation files.
- // Therefor we can just return false. Otherwise we should have returned a dictionairy.
+ // The translations for the default modules are defined in the core translation files.
+ // Therefor we can just return false. Otherwise we should have returned a dictionary.
// If you're trying to build yiur own module including translations, check out the documentation.
return false;
},
diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md
index 9f7b2e7d..7c4ad48d 100644
--- a/modules/default/newsfeed/README.md
+++ b/modules/default/newsfeed/README.md
@@ -70,6 +70,8 @@ The following properties can be configured:
| `updateInterval` | How often do you want to display a new headline? (Milliseconds)
**Possible values:**`1000` - `60000` **Default value:** `10000` (10 seconds)
| `animationSpeed` | Speed of the update animation. (Milliseconds)
**Possible values:**`0` - `5000` **Default value:** `2500` (2.5 seconds)
| `maxNewsItems` | Total amount of news items to cycle through. (0 for unlimited)
**Possible values:**`0` - `...` **Default value:** `0`
+| `ignoreOldItems` | Ignore news items that are outdated.
**Possible values:**`true` or `false **Default value:** `false`
+| `ignoreOlderThan` | How old should news items be before they are considered outdated? (Milliseconds)
**Possible values:**`1` - `...` **Default value:** `86400000` (1 day)
| `removeStartTags` | Some newsfeeds feature tags at the **beginning** of their titles or descriptions, such as _[VIDEO]_. This setting allows for the removal of specified tags from the beginning of an item's description and/or title.
**Possible values:**`'title'`, `'description'`, `'both'`
| `startTags` | List the tags you would like to have removed at the beginning of the feed item
**Possible values:** `['TAG']` or `['TAG1','TAG2',...]`
| `removeEndTags` | Remove specified tags from the **end** of an item's description and/or title.
**Possible values:**`'title'`, `'description'`, `'both'`
diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js
index 5094355e..b230fdb1 100644
--- a/modules/default/newsfeed/newsfeed.js
+++ b/modules/default/newsfeed/newsfeed.js
@@ -28,6 +28,8 @@ Module.register("newsfeed",{
updateInterval: 10 * 1000,
animationSpeed: 2.5 * 1000,
maxNewsItems: 0, // 0 for unlimited
+ ignoreOldItems: false,
+ ignoreOlderThan: 24 * 60 * 60 * 1000, // 1 day
removeStartTags: "",
removeEndTags: "",
startTags: [],
@@ -42,9 +44,9 @@ Module.register("newsfeed",{
// Define required translations.
getTranslations: function() {
- // The translations for the defaut modules are defined in the core translation files.
- // Therefor we can just return false. Otherwise we should have returned a dictionairy.
- // If you're trying to build yiur own module including translations, check out the documentation.
+ // The translations for the default modules are defined in the core translation files.
+ // Therefor we can just return false. Otherwise we should have returned a dictionary.
+ // If you're trying to build your own module including translations, check out the documentation.
return false;
},
@@ -202,7 +204,6 @@ Module.register("newsfeed",{
/* registerFeeds()
* registers the feeds to be used by the backend.
*/
-
registerFeeds: function() {
for (var f in this.config.feeds) {
var feed = this.config.feeds[f];
@@ -213,10 +214,10 @@ Module.register("newsfeed",{
}
},
- /* registerFeeds()
+ /* generateFeed()
* Generate an ordered list of items for this configured module.
*
- * attribute feeds object - An object with feeds returned by the nod helper.
+ * attribute feeds object - An object with feeds returned by the node helper.
*/
generateFeed: function(feeds) {
var newsItems = [];
@@ -226,7 +227,9 @@ Module.register("newsfeed",{
for (var i in feedItems) {
var item = feedItems[i];
item.sourceTitle = this.titleForFeed(feed);
- newsItems.push(item);
+ if (!(this.config.ignoreOldItems && ((Date.now() - new Date(item.pubdate)) > this.config.ignoreOlderThan))) {
+ newsItems.push(item);
+ }
}
}
}
@@ -258,7 +261,7 @@ Module.register("newsfeed",{
return false;
},
- /* subscribedToFeed(feedUrl)
+ /* titleForFeed(feedUrl)
* Returns title for a specific feed Url.
*
* attribute feedUrl string - Url of the feed to check.
diff --git a/modules/default/newsfeed/node_helper.js b/modules/default/newsfeed/node_helper.js
index e5243304..af1d32b8 100644
--- a/modules/default/newsfeed/node_helper.js
+++ b/modules/default/newsfeed/node_helper.js
@@ -24,14 +24,13 @@ module.exports = NodeHelper.create({
}
},
- /* createFetcher(url, reloadInterval)
- * Creates a fetcher for a new url if it doesn't exist yet.
- * Otherwise it reoses the existing one.
+ /* createFetcher(feed, config)
+ * Creates a fetcher for a new feed if it doesn't exist yet.
+ * Otherwise it reuses the existing one.
*
- * attribute url string - URL of the news feed.
- * attribute reloadInterval number - Reload interval in milliseconds.
+ * attribute feed object - A feed object.
+ * attribute config object - A configuration object containing reload interval in milliseconds.
*/
-
createFetcher: function(feed, config) {
var self = this;
diff --git a/modules/default/weatherforecast/weatherforecast.js b/modules/default/weatherforecast/weatherforecast.js
index b269a44a..b8321b17 100644
--- a/modules/default/weatherforecast/weatherforecast.js
+++ b/modules/default/weatherforecast/weatherforecast.js
@@ -77,8 +77,8 @@ Module.register("weatherforecast",{
// Define required translations.
getTranslations: function() {
- // The translations for the defaut modules are defined in the core translation files.
- // Therefor we can just return false. Otherwise we should have returned a dictionairy.
+ // The translations for the default modules are defined in the core translation files.
+ // Therefor we can just return false. Otherwise we should have returned a dictionary.
// If you're trying to build yiur own module including translations, check out the documentation.
return false;
},
diff --git a/modules/node_modules/node_helper/index.js b/modules/node_modules/node_helper/index.js
index 8d0372bd..37c3e2cb 100644
--- a/modules/node_modules/node_helper/index.js
+++ b/modules/node_modules/node_helper/index.js
@@ -20,7 +20,7 @@ NodeHelper = Class.extend({
},
start: function() {
- console.log("Staring module helper: " + this.name);
+ console.log("Starting module helper: " + this.name);
},
/* socketNotificationReceived(notification, payload)
@@ -45,7 +45,7 @@ NodeHelper = Class.extend({
/* setPath(path)
* Set the module path.
*
- * argument name string - Module name.
+ * argument path string - Module path.
*/
setPath: function(path) {
this.path = path;
@@ -98,9 +98,10 @@ NodeHelper = Class.extend({
// register catch all.
socket.on("*", function(notification, payload) {
- if (notification !== "*")
- //console.log('received message in namespace: ' + namespace);
- self.socketNotificationReceived(notification, payload);
+ if (notification !== "*") {
+ //console.log('received message in namespace: ' + namespace);
+ self.socketNotificationReceived(notification, payload);
+ }
});
});
diff --git a/package.json b/package.json
index 7a1e7641..c3bdae63 100644
--- a/package.json
+++ b/package.json
@@ -1,15 +1,16 @@
{
"name": "magicmirror",
- "version": "2.1.1",
- "description": "A modular interface for smart mirrors.",
+ "version": "2.1.2-dev",
+ "description": "The open source modular smart mirror platform.",
"main": "js/electron.js",
"scripts": {
"start": "sh run-start.sh",
"install": "cd vendor && npm install",
"postinstall": "sh installers/postinstall/postinstall.sh",
- "test": "./node_modules/mocha/bin/mocha tests --recursive",
- "test:unit": "./node_modules/mocha/bin/mocha tests/unit --recursive",
- "test:e2e": "./node_modules/mocha/bin/mocha tests/e2e --recursive"
+ "test": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests --recursive",
+ "test:unit": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/unit --recursive",
+ "test:e2e": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/e2e --recursive",
+ "config:check": "node tests/configs/check_config.js"
},
"repository": {
"type": "git",
@@ -29,7 +30,7 @@
"bugs": {
"url": "https://github.com/MichMich/MagicMirror/issues"
},
- "homepage": "https://github.com/MichMich/MagicMirror#readme",
+ "homepage": "https://magicmirror.builders",
"devDependencies": {
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
@@ -39,6 +40,7 @@
"grunt-markdownlint": "^1.0.13",
"grunt-stylelint": "latest",
"grunt-yamllint": "latest",
+ "jshint": "^2.9.4",
"http-auth": "^3.1.3",
"mocha": "^3.2.0",
"spectron": "^3.4.1",
@@ -46,6 +48,7 @@
"time-grunt": "latest"
},
"dependencies": {
+ "body-parser": "^1.17.1",
"colors": "^1.1.2",
"electron": "^1.4.7",
"express": "^4.14.0",
diff --git a/tests/configs/check_config.js b/tests/configs/check_config.js
new file mode 100644
index 00000000..fa294761
--- /dev/null
+++ b/tests/configs/check_config.js
@@ -0,0 +1,66 @@
+/* Magic Mirror
+ *
+ * Checker configuration file
+ *
+ * By Rodrigo Ramírez Norambuena
+ * https://rodrigoramirez.com
+ *
+ * MIT Licensed.
+ *
+ */
+
+var v = require("jshint");
+var path = require("path");
+var fs = require("fs");
+var Utils = require(__dirname + "/../../js/utils.js");
+
+if (process.env.NODE_ENV == "test") {return 0};
+
+/* getConfigFile()
+ * Return string with path of configuration file
+ * Check if set by enviroment variable MM_CONFIG_FILE
+ */
+function getConfigFile() {
+ // FIXME: This function should be in core. Do you want refactor me ;) ?, be good!
+ rootPath = path.resolve(__dirname + "/../../");
+ var configFileName = path.resolve(rootPath + "/config/config.js");
+ if (process.env.MM_CONFIG_FILE) {
+ configFileName = path.resolve(process.env.MM_CONFIG_FILE);
+ }
+ return configFileName;
+}
+
+var configFileName = getConfigFile();
+// Check if file is present
+if (fs.existsSync(configFileName) === false) {
+ console.error(Utils.colors.error("File not found: "), configFileName);
+ return;
+}
+// check permision
+try {
+ fs.accessSync(configFileName, fs.F_OK);
+} catch (e) {
+ console.log(Utils.colors.error(e));
+ return;
+}
+
+// Validate syntax of the configuration file.
+// In case the there errors show messages and
+// return
+console.info(Utils.colors.info("Checking file... ", configFileName));
+ // I'm not sure if all ever is utf-8
+fs.readFile(configFileName, "utf-8", function(err, data) {
+ if (err) {throw err;}
+ v.JSHINT(data); // Parser by jshint
+
+ if (v.JSHINT.errors.length == 0) {
+ console.log("Your configuration file don't containt syntax error :)");
+ return true;
+ } else {
+ errors = v.JSHINT.data().errors;
+ for (idx in errors) {
+ error = errors[idx];
+ console.log("Line", error.line, "col", error.character, error.reason);
+ }
+ }
+});
diff --git a/tests/configs/data/feed_test_rodrigoramirez.xml b/tests/configs/data/feed_test_rodrigoramirez.xml
new file mode 100644
index 00000000..e4d3730f
--- /dev/null
+++ b/tests/configs/data/feed_test_rodrigoramirez.xml
@@ -0,0 +1,410 @@
+
+
+
+ Rodrigo Ramírez Norambuena
+
+ https://rodrigoramirez.com
+ Temas sobre Linux, VoIP, Open Source, tecnología y lo relacionado.
+ Fri, 21 Oct 2016 21:30:22 +0000
+ es-ES
+ hourly
+ 1
+ https://wordpress.org/?v=4.7.3
+
+ QPanel 0.13.0
+ https://rodrigoramirez.com/qpanel-0-13-0/
+ https://rodrigoramirez.com/qpanel-0-13-0/#comments
+ Tue, 20 Sep 2016 11:16:08 +0000
+
+
+
+
+
+
+
+
+
+
+
+
+ https://rodrigoramirez.com/?p=1299
+ Ya está disponible la versión 0.13.0 de QPanel Para instalar esta nueva versión, la debes descargar de https://github.com/roramirez/qpanel/tree/0.13.0 En al README.md puedes encontrar las instrucciones para hacer que funcione en tu sistema. En esta nueva versión cuenta con los siguientes cambios: Se establece un limite para el reciclado del tiempo de conexión a la base […]
+
En al README.md puedes encontrar las instrucciones para hacer que funcione en tu sistema.
+
En esta nueva versión cuenta con los siguientes cambios:
+
+
Se establece un limite para el reciclado del tiempo de conexión a la base de datos que contenga QueueLog. Esto evita problemas en bases de datos como MySQL que finaliza o da timeout a las conexiones.
+
Ahora la py-asterisk va dentro del archivo requirements.txt y no como submodulo del proyecto.
+
Se remueven la mayoría de las libs externas para Javascript y CSS para manejarlos desde ahora con Bower.
+
Se incluye un script para WSGI que permite su utilización con Apache.
+
Actualización para los idiomas Ruso y Portugues.
+
+
Si deseas colaborar con el proyecto puedes agregar nuevas sugerencias mediante un issue ó colaborar mediante mediante un Pull Request.
+]]>
+ https://rodrigoramirez.com/qpanel-0-13-0/feed/
+ 3
+
+
+ Problema VirtualBox “starting virtual machine” …
+ https://rodrigoramirez.com/problema-virtualbox-starting-virtual-machine/
+ https://rodrigoramirez.com/problema-virtualbox-starting-virtual-machine/#respond
+ Sat, 10 Sep 2016 22:50:13 +0000
+
+
+
+
+
+
+ https://rodrigoramirez.com/?p=1284
+ Después de una actualización de Debian, de la rama stretch/sid, tuve un problema con VirtualBox. La versión que se actualizó fue a la virtualbox 5.1.4-dfsg-1+b1. El gran problema era que ninguna maquina virtual quería arrancar, se quedaba en un largo limbo con el mensaje “starting virtual machine”, como el de la imagen de a continuación. […]
+
+]]>
+ Después de una actualización de Debian, de la rama stretch/sid, tuve un problema con VirtualBox. La versión que se actualizó fue a la virtualbox 5.1.4-dfsg-1+b1. El gran problema era que ninguna maquina virtual quería arrancar, se quedaba en un largo limbo con el mensaje “starting virtual machine”, como el de la imagen de a continuación.
+
+
Ninguna, pero ninguna maquina arrancó, se quedaban en ese mensaje. Fue de esos instantes en que sudas helado …
+
Con un poco de investigación fue a parar al archivo ~/.VirtualBox/VBoxSVC.log que indicaba
+
$ tail -f ~/.VirtualBox/VBoxSVC.log
+ 00:08:32.932717 nspr-7 Failed to open "/dev/vboxdrvu", errno=13, rc=VERR_VM_DRIVER_NOT_ACCESSIBLE
+ 00:08:33.555836 nspr-6 Failed to open "/dev/vboxdrvu", errno=13, rc=VERR_VM_DRIVER_NOT_ACCESSIBLE
+
+
Fui… algo de donde agarrarse. Mirando un poco mas se trataba de problemas con los permisos al vboxdrvu, mirando indicaba que tenía 0600.
+]]>
+ https://rodrigoramirez.com/problema-virtualbox-starting-virtual-machine/feed/
+ 0
+
+
+ Mejorando la consola interactiva de Python
+ https://rodrigoramirez.com/mejorando-la-consola-interactiva-python/
+ https://rodrigoramirez.com/mejorando-la-consola-interactiva-python/#comments
+ Tue, 06 Sep 2016 04:24:43 +0000
+
+
+
+
+
+ https://rodrigoramirez.com/?p=1247
+ Cuando estás desarrollando en Python es muy cool estar utilizando la consola interactiva para ir probando cosas antes de ponerlas dentro del archivo de código fuente. La consola de Python funciona y cumple su cometido. Solo al tipear python te permite entrar en modo interactivo e ir probando cosas. El punto es que a veces […]
+
+]]>
+ Cuando estás desarrollando en Python es muy cool estar utilizando la consola interactiva para ir probando cosas antes de ponerlas dentro del archivo de código fuente.
+
La consola de Python funciona y cumple su cometido. Solo al tipear python te permite entrar en modo interactivo e ir probando cosas.
+
El punto es que a veces uno necesita ir un poco más allá. Como autocomentado de código o resaltado de sintaxis, para eso tengo dos truco que utilizo generalmente.
+
Truco a)
+
Este permite añadirle algunos esteriodes a la consolta, en realidad uno, el autocompletado. Esto es de gran ayuda para ir conociendo los metodo que puede tener un objecto, funciones u operaciones.
+
Para esto se ocupo rlcompleter y readline.
+
+
Lo que hace que hacer luego de tipear python es agregar lo siguiente dentro de la consola interativa
Esto es mejorar un poco más. Es utilizar embed de IPython, ya en la consola digita (copias o pegas) lo siguiente
+
from IPython import embed
+embed()
+
Y el resultado será lo que se ve a continuación… bueno, no?
+
+
+
+
Si no quieres estar escribiendo cada vez que entras, agregas estas instrucciones en tu archivo ~/.pythonrc.py y lo hará cada vez que entras en el modo interactivo de la consola de Python. Lo que si, tu archivo pythonrc.py debe estar seteado en variable de entorno PYTHONSTARTUP
+
ejemplo
+
export PYTHONSTARTUP=~/.pythonrc.py
+
O lo agregas a un bashrc, zshrc o la shell que ocupes.
+]]>
+ https://rodrigoramirez.com/mejorando-la-consola-interactiva-python/feed/
+ 4
+
+
+ QPanel 0.12.0 con estadísticas
+ https://rodrigoramirez.com/qpanel-0-12-0-estadisticas/
+ https://rodrigoramirez.com/qpanel-0-12-0-estadisticas/#respond
+ Mon, 22 Aug 2016 04:19:03 +0000
+
+
+
+
+
+
+
+
+
+
+
+
+ https://rodrigoramirez.com/?p=1268
+ Ya está disponible una nueva versión de QPanel, esta es la 0.12.0 Para instalar esta nueva versión, debes visitar la siguiente URL https://github.com/roramirez/qpanel/tree/0.12.0 En esta nueva versión las funcionalidades agregadas son: Permite remover los agentes de las cola Posibilidad de cancelar llamadas que están en espera de atención Estadísticas por rango de fecha obtenidas desde […]
+
+]]>
+ https://rodrigoramirez.com/qpanel-0-12-0-estadisticas/feed/
+ 0
+
+
+ QPanel 0.11.0 con Spy, Whisper y mas
+ https://rodrigoramirez.com/qpanel-spy-supervisor/
+ https://rodrigoramirez.com/qpanel-spy-supervisor/#comments
+ Thu, 21 Jul 2016 01:53:21 +0000
+
+
+
+
+
+
+
+
+
+
+
+
+ https://rodrigoramirez.com/?p=1245
+ Ya está disponible una nueva versión de QPanel, esta es la 0.11.0 Para instalar esta nueva versión, debes visitar la siguiente URL https://github.com/roramirez/qpanel/tree/0.11.0 Esta versión hemos agregado algunas funcionalidades que los usuarios han ido solicitando. Para esta versión es posible realizar Spy, Whisper o Barge a un canal para la supervisión de los miembros que […]
+
+]]>
+ https://rodrigoramirez.com/qpanel-spy-supervisor/feed/
+ 4
+
+
+ Añadir Swap a un sistema
+ https://rodrigoramirez.com/crear-swap/
+ https://rodrigoramirez.com/crear-swap/#respond
+ Fri, 15 Jul 2016 05:07:43 +0000
+
+
+
+ https://rodrigoramirez.com/?p=1234
+ Algo que me toma generalmente hacer es cuando trabajo con maquina virtuales es asignar una cantidad determinada de Swap. La memoria swap es un espacio de intercambio en disco para cuando el sistema ya no puede utilizar más memoria RAM. El problema para mi es que algunos sistemas de maquinas virtuales no asignan por defecto […]
+
+]]>
+ Algo que me toma generalmente hacer es cuando trabajo con maquina virtuales es asignar una cantidad determinada de Swap.
+
La memoria swap es un espacio de intercambio en disco para cuando el sistema ya no puede utilizar más memoria RAM.
+
El problema para mi es que algunos sistemas de maquinas virtuales no asignan por defecto un espacio para la Swap, lo que te lleva a que el sistema pueda tener crash durante la ejecución.
+
Para comprobar la asignación de memoria, al ejecutar el comando free nos debería mostrar como algo similar a lo siguiente
En la zona de swap indica que no asignada, valor 0.
+
Para asignar swap al sistema se debe un archivo en disco para que sea utilizado como espacio de intercambio, en este caso lo vamos crear uno de 3GB en la raíz del sistema
+]]>
+ https://rodrigoramirez.com/crear-swap/feed/
+ 0
+
+
+ QPanel 0.10.0 con vista consolidada
+ https://rodrigoramirez.com/qpanel-0-10-0-vista-consolidada/
+ https://rodrigoramirez.com/qpanel-0-10-0-vista-consolidada/#respond
+ Mon, 20 Jun 2016 19:32:55 +0000
+
+
+
+
+
+
+
+
+ https://rodrigoramirez.com/?p=1227
+ Ya con la release numero 28 la nueva versión 0.10.0 de QPanel ya está disponible. Para instalar esta nueva versión, debes visitar la siguiente URL https://github.com/roramirez/qpanel/tree/0.10.0 Esta versión versión nos preocupamos de realizar mejoras, refactorizaciones y agregamos una nueva funcionalidad. La nueva funcionalidad incluida es que ahora es posible contar con una vista consolidada para […]
+
Esta versión versión nos preocupamos de realizar mejoras, refactorizaciones y agregamos una nueva funcionalidad.
+
La nueva funcionalidad incluida es que ahora es posible contar con una vista consolidada para la información de todas las colas. Que hace tener un mejor control y visualización de lo que está pasando en las colas.
+
El proyecto siempre está abierto a nuevas sugerencias las cuales puedes agregar mediante un issue.
+]]>
+ https://rodrigoramirez.com/qpanel-0-10-0-vista-consolidada/feed/
+ 0
+
+
+ Nerdearla 2016, WebRTC Glue
+ https://rodrigoramirez.com/nerdearla-2016/
+ https://rodrigoramirez.com/nerdearla-2016/#respond
+ Wed, 15 Jun 2016 17:55:41 +0000
+
+
+
+
+
+
+
+
+
+
+ https://rodrigoramirez.com/?p=1218
+ Días atrás estuve participando en el evento llamado Nerdearla en Buenos Aires. El ambiente era genial si eres de esas personas que desde niño sintio curiosidad por ver como funcionan las cosas, donde desarmabas para volver armar lo juguetes. Habían muchas cosas interesantes tanto en las presentaciones, co-working y workshop que se hubieron. Si te […]
+
+]]>
+ Días atrás estuve participando en el evento llamado Nerdearla en Buenos Aires. El ambiente era genial si eres de esas personas que desde niño sintio curiosidad por ver como funcionan las cosas, donde desarmabas para volver armar lo juguetes.
+
Habían muchas cosas interesantes tanto en las presentaciones, co-working y workshop que se hubieron. Si te lo perdiste te recomiendo que estés pendiente para el proximo año.
El primer día hice un workshop denominado WebRTC Glue, donde muestra como hacer como unificar la experiencia de atención del centro de contacto directamente en la web. Es una presentación práctica donde puedes ver los ejemplos y usarlos como gustes. Están en el repositorio en Gitlab. La presentación la puedes ver aquí
+
+
+
Haber si nos vemos el próximo año.
+
+
Update: Puedes ver una parte sin la demostración del workshop
+]]>
+ https://rodrigoramirez.com/nerdearla-2016/feed/
+ 0
+
+
+ QPanel 0.9.0
+ https://rodrigoramirez.com/qpanel-0-9-0/
+ https://rodrigoramirez.com/qpanel-0-9-0/#respond
+ Mon, 09 May 2016 18:40:23 +0000
+
+
+
+
+
+
+
+
+
+
+
+ http://rodrigoramirez.com/?p=1206
+ El Panel monitor callcenter para colas de Asterisk ya cuenta con una nueva versión, la 0.9.0 Para instalar esta nueva versión, debes visitar la siguiente URL https://github.com/roramirez/qpanel/tree/0.9.0 Esta versión versión nos preocupamos de realizar mejoras y refactorizaciones en el codigo para dar un mejor rendimiento, como también de la compatibilidad con la versión 11 de […]
+
Esta versión versión nos preocupamos de realizar mejoras y refactorizaciones en el codigo para dar un mejor rendimiento, como también de la compatibilidad con la versión 11 de Asterisk.
+
Dentro de las cosas que podamos mencionar:
+
+
Actualización del repositorio y versión de py-asterisk, biblioteca para trabajar con Asterisk. Acá la ocupamos principalmente para uso del Manager.
+
Portación de parche de funcionalidades como pausa, tiempo, razón de una pausa para Asterisk 11.
+
Cambio del comportamiento en el conteo cuando el participante en una cola está ocupado (busy)
+
+
El proyecto siempre está abierto a nuevas sugerencias las cuales puedes agregar mediante un issue.
+]]>
+ https://rodrigoramirez.com/qpanel-0-9-0/feed/
+ 0
+
+
+ Mandar un email desde la shell
+ https://rodrigoramirez.com/mandar-un-email-desde-la-shell/
+ https://rodrigoramirez.com/mandar-un-email-desde-la-shell/#comments
+ Wed, 13 Apr 2016 13:05:13 +0000
+
+
+
+
+
+
+
+
+
+
+ http://rodrigoramirez.com/?p=1172
+ Dejo esto por acá ya que es algo que siempre me olvido como es. El tema es enviar un email mediante el comando mail en un servidor con Linux. Si usas mail a secas te va pidiendo los datos para crear el correo, principalmente el body del correo. Para automatizar esto a través de un […]
+
+]]>
+ Dejo esto por acá ya que es algo que siempre me olvido como es. El tema es enviar un email mediante el comando mail en un servidor con Linux.
+
Si usas mail a secas te va pidiendo los datos para crear el correo, principalmente el body del correo. Para automatizar esto a través de un echo le pasas por pipe a mail
+
echo "Cuerpo del mensaje" | mail -s Asunto a@rodrigoramirez.com