[PHP] docomo 雑談対話 API

docomo が提供してくれている 雑談対話API をさくっと php で使う方法。

<?php
/*****
* https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_docs_id=5
*****/
function webnist($text) {
$context_file = dirname(__FILE__).'/.docomoapi.context';
$api_key = 'your API key here';
$api_url = sprintf('https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=%s&#39;, $api_key);
$req_body = array('utt' => $text);
if ( file_exists($context_file) ) {
$req_body['context'] = file_get_contents($context_file);
}
$headers = array(
'Content-Type: application/json; charset=UTF-8',
);
$options = array(
'http'=>array(
'method' => 'POST',
'header' => implode( "\r\n", $headers ),
'content' => json_encode($req_body),
)
);
$stream = stream_context_create( $options );
$res = json_decode(file_get_contents($api_url, false, $stream));
if (isset($res->context)) {
file_put_contents($context_file, $res->context);
}
return isset($res->utt) ? $res->utt : '';
}

curl で試したいときは、こんな感じ

curl -s --insecure \
 -H "Content-Type: application/json; charset=UTF-8" \
 https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=XXXXXX \
 -d "{\"utt\":\"アイス食べたい\"}"

view raw
gistfile1.md
hosted with ❤ by GitHub

まともに使いたければ https://github.com/fetus-hina/docomo-dialogue とかのライブラリ使うといいと思うよ。

[AWS] Lambda から Lambda を呼ぶ

ようやく AWS Lambda が把握できてきた。
小さい機能単位で Lambda ファンクション作って、それを呼ぶ感じで作っていくとやりやすい。

イベント発生して呼び出される Lambda ファンクション

イベントの情報をもとになんかする Lambda ファンクション

結果を SNS なり、Slack なりに投げる Lambda ファンクション

みたいに Lambda ファンクションから Lambda ファンクションを呼び出して作業させると具合がいい
Lambda から Lambda を呼ぶには

console.log('Loading event');
var aws = require('aws-sdk');

exports.handler = function(event, context) {
    // なんか処理

    var lambda = new aws.Lambda({apiVersion: '2014-11-11'});
    var params = {
        FunctionName: "lambda-function-name",
        InvokeArgs: JSON.stringify({
            "key_1": 'var_1',
            "key_2": 'var_2',
            "key_3": 'var_3'
            }, null, ' ')
        };
    lambda.invokeAsync(params, function(err, data){
        if(err) context.done('error', err.stack);
        else context.done(null, '');
}

Lambda から SNS を呼ぶには

var sns = new aws.SNS({region: 'リージョン'});
var params = {
    TopicArn: 'トピック arn',
    Subject: 'サブジェクト',
    Message: 'メッセージ'
  };
  sns.publish(params, function(err, data) {
    if(err) context.done('error', err.stack);
    else context.done(null, '');
  })

[AWS] Lambda でS3 にファイルをアップロードしたら typetalk チャットに通知するやつ

参考: AWS Lambda でS3 にファイルをアップロードしたらSlackチャットに通知するやつ

元記事では Slack だったけど、typetalk も業務でお世話になってるので、Typetalk 対応もしてみた。
Typetalk API

const TYPETALK_TOKEN = "....";

var req = require('request');

exports.handler = function(event, context) {
    var filename = event.Records[0].s3.object.key;
    typetalk(TYPETALK_TOKEN, "your typetalk toppick id", "Put: "+filename);
};

function typetalk(token, topic_id, message) {
    req.post('https://typetalk.in/api/v1/topics/'+topic_id+'?typetalkToken='+token)
        .form({
            message: message
        })
        .on('response', function (response) {
          response.on('data', function(data) {
            context.done(null, data);
          });
        })
        .on('error', function (err) {
            cotext.done(err, 'Failed post the chat');
        });
}

https://github.com/wokamoto/aws-lambda-samples/tree/master/s3slack

[PHP] Google Calendar API v3 で日本の祝日を取得する

下準備

  • Google APIs ConsoleでCalendar APIのステータスをONにする
  • Google API keyを取得する
<?php
function get_holidays_this_month($year, $month){
// 月初日
$first_day = mktime(0, 0, 0, intval($month), 1, intval($year));
// 月末日
$last_day = strtotime('-1 day', mktime(0, 0, 0, intval($month) + 1, 1, intval($year)));
$api_key = 'YOUR API KEY HERE';
$holidays_id = 'outid3el0qkcrsuf89fltf7a4qbacgt9@import.calendar.google.com'; // mozilla.org版
//$holidays_id = 'japanese__ja@holiday.calendar.google.com'; // Google 公式版日本語
//$holidays_id = 'japanese@holiday.calendar.google.com'; // Google 公式版英語
$holidays_url = sprintf(
'https://www.googleapis.com/calendar/v3/calendars/%s/events?&#39;.
'key=%s&timeMin=%s&timeMax=%s&maxResults=%d&orderBy=startTime&singleEvents=true',
$holidays_id,
$api_key,
date('Y-m-d', $first_day).'T00:00:00Z' , // 取得開始日
date('Y-m-d', $last_day).'T00:00:00Z' , // 取得終了日
31 // 最大取得数
);
if ( $results = file_get_contents($holidays_url) ) {
$results = json_decode($results);
$holidays = array();
foreach ($results->items as $item ) {
$date = strtotime((string) $item->start->date);
$title = (string) $item->summary;
$holidays[date('Y-m-d', $date)] = $title;
}
ksort($holidays);
}
return $holidays;
}

view raw
gistfile1.php
hosted with ❤ by GitHub

9行目の $api_key = 'YOUR API KEY HERE'; って所を取得してきた Google API Key に書き換えてください。

[PHP] 非公開領域にある pdf をダウンロードさせる

ログインとかしてないと pdf をダウンロードできないようにしようと思って、pdf を非公開領域に置いて、いかのようなコードを書いたんですよ。

<?php
$mime_type = 'application/pdf';
$file_path = '/path/to/pdf';
header('Content-Disposition: inline; filename="'.basename($file_path).'"');
header('Content-Length: '.filesize($file_path));
header('Content-Type: '.$mime_type);
readfile($file_path);

view raw
gistfile1.php
hosted with ❤ by GitHub

そしたら https な環境で IE 8 からダウンロードできないってクレームががが…

IE5 – IE8 では https 環境で Cache-control:no-cache へっだが付いてるとダウンロードできないんですって…
Internet Explorer file downloads over SSL do not work with the cache control headers

そこで以下のようになおしました。

<?php
$mime_type = 'application/pdf';
$file_path = '/path/to/pdf';
// for IE 8 ( see http://support.microsoft.com/kb/323308/ja )
$expires = 30;
header("Last-Modified: ". gmdate("D, d M Y H:i:s", filemtime($file_path)). " GMT");
header("Expires: " . date(DATE_RFC1123, time() + $expires));
header("Pragma: cache");
header("Cache-Control: max-age={$expires}");
header("Cache-Control: cache");
// for IE 8
header('Content-Disposition: inline; filename="'.basename($file_path).'"');
header('Content-Length: '.filesize($file_path));
header('Content-Type: '.$mime_type);
readfile($file_path);

view raw
gistfile1.php
hosted with ❤ by GitHub

IE8めー

[PHP] ISBN のチェック

たまには写経を

ISBN は、誤り検出のため各数字の重み付き合計が 11 の倍数になるように最後の数字が調節されている。
最後の数字のみ 10 にしたい場合は X で表す。(via. C言語によるアルゴリズム辞典 P.371)

<?php
var_dump(validISBN('4-87408-414-1'));
function validISBN($isbn) {
if (preg_match('/^(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?([\dX])$/i', $isbn, $d)) {
$d[0] = 0;
foreach ( $d as $key => &$val ) {
$val = ($key == 10 && ($val == 'x' || $val == 'X')) ? 10 : intval($val);
}
for ( $i = 1; $i <= 10; $i++ ) {
$d[$i] += $d[$i1];
}
for ( $i = 1; $i <= 10; $i++ ) {
$d[$i] += $d[$i1];
}
return ($d[10] % 11 == 0);
} else {
return false;
}
}

view raw
valid-isbn.php
hosted with ❤ by GitHub

[PHP][AWS] AWS SDK for PHP 2 で S3 にファイルをアップロード

<?php
require_once("aws.phar");
use Aws\Common\Aws;
use Aws\Common\Enum\Region;
use Aws\S3\Enum\CannedAcl;
use Aws\S3\Exception\S3Exception;
use Guzzle\Http\EntityBody;
$access_key = 'Your Access Key';
$secret_key = 'Your Secret Key';
$region = Region::AP_NORTHEAST_1; // Region::AP_NORTHEAST_1 = Tokyo Region
$bucket = 's3_bucket_name';
try {
// S3
$s3 = Aws::factory(array(
'key' => $access_key,
'secret' => $secret_key,
'region' => $region,
))->get('s3');
$info = new FInfo(FILEINFO_MIME_TYPE);
// Upload File
$filename = 'test.txt';
$filebody = EntityBody::factory(fopen($filename, 'r'));
$filetype = $info->file($filename);
$response = $s3->putObject(array(
'Bucket' => $bucket,
'Key' => $filename,
'Body' => $filebody,
'ContentType' => $filetype,
'StorageClass' => 'STANDARD', // STANDARD or REDUCED_REDUNDANCY
//'ServerSideEncryption => 'AES256',
'ACL' => CannedAcl::PUBLIC_READ, // PUBLIC_READ, PRIVATE_ACCESS…
));
var_dump($response);
} catch (S3Exception $e) {
}

view raw
upload-s3.php
hosted with ❤ by GitHub

Region の設定値: PHP 2: Class Aws\Common\Enum\Region | AWS SDK for PHP 2
ACL の設定値: PHP 2: Class Aws\S3\Enum\CannedAcl | AWS SDK for PHP 2

[PHP] Twitter Search API の使い方

<?php
$search_word = 'http://example.com/&#39;;
$page_per_posts = 100;
$twitter_search_api = sprintf(
'http://search.twitter.com/search.json?q=%s&rpp=%d&#39;,
urlencode($search_word),
$page_per_posts
);
$results = array();
if ( $response = file_get_contents($twitter_search_api) ) {
$json = json_decode($response);
$list = (array)(isset($json->results) ? $json->results : array());
foreach ( $list as $item ){
$results[$item->id_str] = array(
'author' => $item->from_user_name ,
'author_id' => $item->from_user_id_str ,
'profile_url' => $item->profile_image_url ,
'tweet_url' => sprintf('https://twitter.com/%s/status/%s&#39;, $item->from_user, $item->id_str) ,
'datetime' => (int) strtotime($item->created_at) ,
'content' => $item->text ,
'geo' => $item->geo ,
'language' => $item->iso_language_code ,
);
}
}

$search_word は検索したい文字列、$page_per_posts は一度に取得するツイート数、$results に検索結果が入るよ。

via. GET search | Twitter Developers

Re: phpで日本の祝日や振替休日を出力する。

とりあえず1か月分の祝日を取得します。ついでに振替休日やら、国民の休日にも対応してみました。国民の休日なんてめったにあるもんじゃないんですけど、2015年にまたあるようなので、とりあえず実装してみました。イベントスケジュールとかを作るときに結構便利です。

via. phpで日本の祝日や振替休日を出力する。 ::: Toro_Unit

引数には、年も指定できた方が良いですね。

<?php
function get_holidays_this_month($year, $month){
// 月初日
$first_day = mktime(0, 0, 0, intval($month), 1, intval($year));
// 月末日
$last_day = strtotime('-1 day', mktime(0, 0, 0, intval($month) + 1, 1, intval($year)));
$holidays_url = sprintf(
'http://www.google.com/calendar/feeds/%s/public/full-noattendees?start-min=%s&amp;start-max=%s&amp;max-results=%d&amp;alt=json&#39; ,
'japanese__ja@holiday.calendar.google.com' ,
date('Y-m-d', $first_day) , // 取得開始日
date('Y-m-d', $last_day) , // 取得終了日
31 // 最大取得数
);
if ( $results = file_get_contents($holidays_url) ) {
$results = json_decode($results, true);
$holidays = array();
foreach ($results['feed']['entry'] as $val ) {
$date = $val['gd$when'][0]['startTime'];
$week = date('w',strtotime($date));
$title = $val['title']['$t'];
$holidays[$date] = $title;
if( $week == 0) {
$nextday = date('Y-m-d',strtotime('+1 day', strtotime($date)));
$holidays[$nextday] = '振替休日';
}
$before_yesterday = date('Y-m-d',strtotime('-2 day', strtotime($date)));
if(isset($holidays[$before_yesterday])){
$yesterday = date('Y-m-d',strtotime('-1 day', strtotime($date)));
$holidays[$yesterday] = '国民の休日';
}
}
ksort($holidays);
}
return $holidays;
}

[2014-8-26 追記] Google Calendar API v3 に対応させる記事を書きました
[PHP] Google Calendar API v3 で日本の祝日を取得する

[PHP] 10進数をn進数に変換

<?php
function dec_to_n( $dec, $n = 62, $disits = null ) {
if ( !$disits ) {
$disits = array(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
);
}
$max_n = count($disits);
if ( ! (preg_match('/^\d+$/', $n) && $n >= 2 && $n <= $max_n) ) return FALSE;
if ( ! preg_match('/^\d+$/', $dec) ) return FALSE;
if ( $dec == 0 ) return $dec;
$num_str = '';
while ( $dec !== 0 ) {
$num_str = $disits[$dec % $n] . $num_str;
$dec = (int) ($dec / $n);
}
return $num_str;
}
function n_to_dec( $num_str, $n = 62, $disits = null ) {
if ( !$disits ) {
$disits = array(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
);
}
$max_n = count($disits);
$valids = array();
for ( $i = 0; $i < $max_n; $i++ ) {
$valids[$disits[$i]] = $i;
}
if ( ! (preg_match('/^\d+$/', $n) && $n >= 2 && $n <= $max_n) ) return FALSE;
if ( ! preg_match('/^[\da-zA-Z]+$/', $num_str) ) return FALSE;
$dec = 0;
for ( $i = 0; $i < strlen($num_str); $i++ ) {
$dec += $valids[ substr($num_str, ($i + 1) * –1, 1) ] * pow( $n, $i );
}
return $dec;
}

view raw
dec_to_n.php
hosted with ❤ by GitHub