mirror of
https://github.com/ivuorinen/xkcd-Mailer.git
synced 2026-02-18 09:53:44 +00:00
1.0.0
This commit is contained in:
@@ -7,8 +7,11 @@ root = true
|
|||||||
[*]
|
[*]
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
# 4 space indentation
|
# 4 space indentation
|
||||||
[*.php]
|
[*.php]
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_size = 2
|
||||||
|
|||||||
37
.github/workflows/phpcs.yml
vendored
Normal file
37
.github/workflows/phpcs.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: PHP CS Checks
|
||||||
|
|
||||||
|
on: [ push ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
phpcs-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Validate composer.json and composer.lock
|
||||||
|
run: composer validate
|
||||||
|
|
||||||
|
- name: Cache Composer packages
|
||||||
|
id: composer-cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: vendor
|
||||||
|
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-php-
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: 7.4
|
||||||
|
extensions: simplexml
|
||||||
|
coverage: xdebug
|
||||||
|
env:
|
||||||
|
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Run PHPCS Check
|
||||||
|
run: |
|
||||||
|
composer install --prefer-dist --no-progress
|
||||||
|
composer require staabm/annotate-pull-request-from-checkstyle
|
||||||
|
./vendor/bin/phpcs -q --report=checkstyle | vendor/bin/cs2pr --graceful-warnings
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
config.php
|
config.php
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
|
last.txt
|
||||||
|
phpcs.xml
|
||||||
|
vendor
|
||||||
|
|||||||
15
CHANGELOG.md
Normal file
15
CHANGELOG.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres
|
||||||
|
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [1.0.0] - 2021-11-12
|
||||||
|
|
||||||
|
- Initial real release, of a 23 Aug 2010 started project.
|
||||||
|
- Added PHP_CodeSniffer
|
||||||
|
- Refactored the codebase for fun
|
||||||
|
- Added this changelog
|
||||||
30
README.md
30
README.md
@@ -1,8 +1,10 @@
|
|||||||
# xkcd-Mailer #
|
# xkcd-Mailer
|
||||||
|
|
||||||
Takes the first/latest item from the [xkcd](http://xkcd.com/) atom-feed and mails the image and punchline to a specified email address, if it has not been sent before.
|
Takes the first/latest item from the [xkcd](http://xkcd.com/) atom-feed
|
||||||
|
and mails the image and punchline to a specified email address,
|
||||||
|
if it has not been sent before.
|
||||||
|
|
||||||
## configuration ##
|
## configuration
|
||||||
|
|
||||||
The script needs a simple configuration. Modify ``config.example.php`` to fit your needs and save as ``config.php``
|
The script needs a simple configuration. Modify ``config.example.php`` to fit your needs and save as ``config.php``
|
||||||
|
|
||||||
@@ -14,7 +16,7 @@ The script needs a simple configuration. Modify ``config.example.php`` to fit yo
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Your timezone, PHP5 required.
|
// Your timezone, PHP5 required.
|
||||||
// See full list: http://www.php.net/manual/en/timezones.php
|
// See full list: https://www.php.net/manual/en/timezones.php
|
||||||
date_default_timezone_set("Europe/Helsinki");
|
date_default_timezone_set("Europe/Helsinki");
|
||||||
|
|
||||||
// Your destination
|
// Your destination
|
||||||
@@ -25,31 +27,33 @@ $from = "xkcd mailer <xkcdmailer@example.com>";
|
|||||||
$lastfile = "last.txt";
|
$lastfile = "last.txt";
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## crontab example
|
||||||
## crontab example ##
|
|
||||||
|
|
||||||
Run every hour.
|
Run every hour.
|
||||||
|
|
||||||
0 * * * * /usr/bin/php /full/path/to/xkcd-mailer.php
|
0 * * * * /usr/bin/php /full/path/to/xkcd-mailer.php
|
||||||
|
|
||||||
This version will check if the last post was already emailed and will only send the post
|
This version will check if the last post was already emailed and will only
|
||||||
if it has not been emailed yet.
|
send the post if it has not been emailed yet.
|
||||||
|
|
||||||
## caveats ##
|
## caveats
|
||||||
|
|
||||||
Make sure to set $lastfile to a path that you have write access to.
|
Make sure to set $lastfile to a path that you have write access to.
|
||||||
|
|
||||||
## changes ##
|
## changes
|
||||||
|
|
||||||
- 2014-03-30 @wojas added check to see if a post already sent
|
- 2014-03-30 @wojas added check to see if a post already sent
|
||||||
|
|
||||||
## contributing ##
|
## contributing
|
||||||
|
|
||||||
- Fork the code
|
- Fork the code
|
||||||
- Do your changes
|
- Do your changes
|
||||||
- Send pull request
|
- Send pull request
|
||||||
- Bask in glory of open source love
|
- Bask in glory of open source love
|
||||||
|
|
||||||
## forks <3 ##
|
## forks <3
|
||||||
|
|
||||||
* [raamdev/pennyarcade-Mailer](https://github.com/raamdev/pennyarcade-Mailer) - [Penny Arcade](http://penny-arcade.com/comic) emailer by Raam Dev
|
* [raamdev/pennyarcade-Mailer][pa-git] - [Penny Arcade][pa-url] emailer by Raam Dev
|
||||||
|
|
||||||
|
[pa-git]: https://github.com/raamdev/pennyarcade-Mailer
|
||||||
|
[pa-url]: http://penny-arcade.com/comic
|
||||||
|
|||||||
32
composer.json
Normal file
32
composer.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "ivuorinen/xkcd-mailer",
|
||||||
|
"description": "XKCD Mailer",
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ismo Vuorinen",
|
||||||
|
"homepage": "https://github.com/ivuorinen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Raam Dev",
|
||||||
|
"homepage": "https://github.com/raamdev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wojas",
|
||||||
|
"homepage": "https://github.com/wojas"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"lint": "phpcs --warning-severity=0 .",
|
||||||
|
"lint-all": "phpcs .",
|
||||||
|
"fix": "phpcbf ."
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-simplexml": "*",
|
||||||
|
"ext-curl": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"squizlabs/php_codesniffer": "^3.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
75
composer.lock
generated
Normal file
75
composer.lock
generated
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "0ed923ad64c14ec9e739afe660e900ad",
|
||||||
|
"packages": [],
|
||||||
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "squizlabs/php_codesniffer",
|
||||||
|
"version": "3.6.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
|
||||||
|
"reference": "f268ca40d54617c6e06757f83f699775c9b3ff2e"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f268ca40d54617c6e06757f83f699775c9b3ff2e",
|
||||||
|
"reference": "f268ca40d54617c6e06757f83f699775c9b3ff2e",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-simplexml": "*",
|
||||||
|
"ext-tokenizer": "*",
|
||||||
|
"ext-xmlwriter": "*",
|
||||||
|
"php": ">=5.4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"bin/phpcs",
|
||||||
|
"bin/phpcbf"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Greg Sherwood",
|
||||||
|
"role": "lead"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
|
||||||
|
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
|
||||||
|
"keywords": [
|
||||||
|
"phpcs",
|
||||||
|
"standards"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
|
||||||
|
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
|
||||||
|
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
|
||||||
|
},
|
||||||
|
"time": "2021-10-11T04:00:11+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.1.0"
|
||||||
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
<?php if ( empty($here) ) exit('No direct script access allowed');
|
<?php
|
||||||
|
|
||||||
|
if (empty($here)) {
|
||||||
|
exit('No direct script access allowed');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xkcd-Mailer configuration example
|
* xkcd-Mailer configuration example
|
||||||
@@ -13,5 +17,11 @@ date_default_timezone_set("Europe/Helsinki");
|
|||||||
$mail = "your@email.com";
|
$mail = "your@email.com";
|
||||||
$from = "xkcd mailer <xkcdmailer@example.com>";
|
$from = "xkcd mailer <xkcdmailer@example.com>";
|
||||||
|
|
||||||
|
// Send using mail (false just echoes the results)
|
||||||
|
$send = true;
|
||||||
|
|
||||||
// File to write ID of last post to
|
// File to write ID of last post to
|
||||||
$lastfile = "last.txt";
|
$lastfile = "last.txt";
|
||||||
|
|
||||||
|
// Debug mode active
|
||||||
|
$debug = false;
|
||||||
|
|||||||
19
phpcs.xml.dist
Normal file
19
phpcs.xml.dist
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset
|
||||||
|
name="PHP_CodeSniffer"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/squizlabs/PHP_CodeSniffer/master/phpcs.xsd"
|
||||||
|
>
|
||||||
|
<description>PHP Code Sniffer configuration file.</description>
|
||||||
|
<arg name="basepath" value="."/>
|
||||||
|
<arg name="colors"/>
|
||||||
|
<arg name="extensions" value="php"/>
|
||||||
|
<arg name="parallel" value="10"/>
|
||||||
|
|
||||||
|
<!-- base rule: set to PSR12-->
|
||||||
|
<!-- https://www.php-fig.org/psr/psr-12/ -->
|
||||||
|
<!-- https://github.com/squizlabs/PHP_CodeSniffer/wiki/Customisable-Sniff-Properties -->
|
||||||
|
<rule ref="PSR12">
|
||||||
|
<exclude-pattern>*/vendor/*</exclude-pattern>
|
||||||
|
</rule>
|
||||||
|
</ruleset>
|
||||||
108
xkcd-mailer.php
108
xkcd-mailer.php
@@ -1,35 +1,53 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xkcd-Mailer
|
* xkcd-Mailer
|
||||||
*
|
*
|
||||||
* Sends HTML-email containing hotlinked latest xkcd
|
* Sends HTML-email containing hotlinked the latest xkcd
|
||||||
* strip with alt/title-text underneath the image.
|
* strip with alt/title-text underneath the image.
|
||||||
*
|
*
|
||||||
* @category Default
|
|
||||||
* @package Default
|
|
||||||
* @author Ismo Vuorinen <ivuorinen@me.com>
|
* @author Ismo Vuorinen <ivuorinen@me.com>
|
||||||
* @author wojas <https://github.com/wojas>
|
* @author wojas <https://github.com/wojas>
|
||||||
* @author Raam Dev <https://github.com/raamdev>
|
* @author Raam Dev <https://github.com/raamdev>
|
||||||
|
* @link https://github.com/ivuorinen/xkcd-Mailer
|
||||||
* @license The MIT License http://www.opensource.org/licenses/mit-license.php
|
* @license The MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
* @version 1.0.20140525
|
* @version 1.0.20140525
|
||||||
* @link https://github.com/ivuorinen/xkcd-Mailer
|
*/
|
||||||
**/
|
|
||||||
|
|
||||||
// Use config.example.php as base for your configurations.
|
// Use config.example.php as base for your configurations.
|
||||||
$lastfile = "last.txt";
|
|
||||||
|
|
||||||
$here = dirname(__FILE__);
|
$here = __DIR__;
|
||||||
if (! is_readable($here . '/config.php')) {
|
if (! is_readable($here . '/config.php')) {
|
||||||
die("Please configure me. I don't know where I should sent the comic. (Config file {$here}/config.php missing.)");
|
die("Please configure me. I don't know where I should sent the comic. (Config file {$here}/config.php missing.)");
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once $here . '/config.php';
|
require_once $here . '/config.php';
|
||||||
|
|
||||||
$feed = "http://xkcd.com/atom.xml";
|
if (! isset($mail, $from) || empty($mail) || empty($from)) {
|
||||||
|
die('Configuration values $mail and $from cannot be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
$lastfile = $lastfile ?? 'last.txt';
|
||||||
|
$debug = $debug ?? false;
|
||||||
|
$send = $send ?? false;
|
||||||
|
|
||||||
|
$feed = "https://xkcd.com/atom.xml";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get xml feed and parse it.
|
||||||
|
* Checks if http(s):// wrapper is allowed.
|
||||||
|
*
|
||||||
|
* @param string $feed Feed to fetch and parse.
|
||||||
|
*
|
||||||
|
* @return \SimpleXMLElement
|
||||||
|
*/
|
||||||
|
function getFeed(string $feed): SimpleXMLElement
|
||||||
|
{
|
||||||
|
if (ini_get('allow_url_fopen')) {
|
||||||
|
// https://bugs.php.net/bug.php?id=62577
|
||||||
|
return simplexml_load_string(file_get_contents($feed));
|
||||||
|
}
|
||||||
|
|
||||||
// Check if http:// wrapper is allowed
|
|
||||||
if (ini_get('allow_url_fopen')) {
|
|
||||||
$data = simplexml_load_file($feed);
|
|
||||||
} else {
|
|
||||||
// If http:// wrapper is disabled (by allow_url_fopen=0, for example), then fall back on cURL
|
// If http:// wrapper is disabled (by allow_url_fopen=0, for example), then fall back on cURL
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
curl_setopt($ch, CURLOPT_URL, $feed);
|
curl_setopt($ch, CURLOPT_URL, $feed);
|
||||||
@@ -40,19 +58,17 @@ if (ini_get('allow_url_fopen')) {
|
|||||||
$result = curl_exec($ch);
|
$result = curl_exec($ch);
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
|
|
||||||
$data = simplexml_load_string($result);
|
return simplexml_load_string($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$data = getFeed($feed);
|
||||||
$item = $data->entry[0];
|
$item = $data->entry[0];
|
||||||
|
|
||||||
$last = 0;
|
$last = file_exists($lastfile)
|
||||||
if (file_exists($lastfile)) {
|
? file_get_contents($lastfile)
|
||||||
$f = fopen($lastfile, 'r');
|
: 0;
|
||||||
$last = (int) fread($f, 1024);
|
|
||||||
fclose($f);
|
|
||||||
}
|
|
||||||
|
|
||||||
$parts = explode('/', $item->id);
|
$parts = explode('/', $item->id, 4);
|
||||||
$current = (int) $parts[3];
|
$current = (int) $parts[3];
|
||||||
|
|
||||||
if ($current > $last) {
|
if ($current > $last) {
|
||||||
@@ -60,25 +76,45 @@ if ($current > $last) {
|
|||||||
preg_match("#title=\"(.+)\"#iU", $item->summary, $t);
|
preg_match("#title=\"(.+)\"#iU", $item->summary, $t);
|
||||||
|
|
||||||
// To send HTML mail, the Content-type header must be set
|
// To send HTML mail, the Content-type header must be set
|
||||||
//$headers = 'MIME-Version: 1.0' . "\r\n";
|
$headers = "Content-type: text/html; charset=UTF-8\r\n" .
|
||||||
$headers = 'Content-type: text/html; charset=UTF-8' . "\r\n";
|
sprintf("From: %s\r\n", $from);
|
||||||
$headers .= 'From: '. $from . "\r\n";
|
|
||||||
|
|
||||||
$subject = "xkcd {$date}: {$item->title}";
|
$subject = sprintf('xkcd %s: %s', $date, $item->title);
|
||||||
$punchline = $t[1];
|
$punchline = $t[1];
|
||||||
|
|
||||||
$msg = "<html><body><h1><a href=\"{$item->id}\">{$item->title}</a></h1>\n"
|
$title = sprintf('<h1><a href="%s">%s</a></h1>', $item->id, $item->title);
|
||||||
. "<small>Posted {$date}</small><br />\n"
|
$body = sprintf(
|
||||||
. $item->summary."<br />\n"
|
'<small>Posted %s</small><br>%s<br><p>%s</p>',
|
||||||
. "<p>{$punchline}</p></body></html>\n";
|
$date,
|
||||||
|
$item->summary,
|
||||||
|
$punchline
|
||||||
|
);
|
||||||
|
|
||||||
mail($mail, $subject, $msg, $headers);
|
$msg = sprintf(
|
||||||
|
"<html lang='en'><body>%s\n%s</body></html>",
|
||||||
|
$title,
|
||||||
|
$body
|
||||||
|
);
|
||||||
|
|
||||||
$f = fopen($lastfile, 'w');
|
if ($send) {
|
||||||
fwrite($f, $current);
|
mail($mail, $subject, $msg, $headers);
|
||||||
fclose($f);
|
} else {
|
||||||
|
echo $msg . "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
echo "New last is $current (was $last)\n";
|
$file_write_result = file_put_contents($lastfile, $current);
|
||||||
} else {
|
|
||||||
echo "No new XKCD: last=$last current=$current\n";
|
if (! $file_write_result) {
|
||||||
|
echo "Error writing to file: $lastfile\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
echo "New last is $current (was $last)\n";
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
echo sprintf("No new XKCD: last=%d current=%d\n", $last, $current);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user