bz0のにっき

quick and dirty prototype

kintone APIのライブラリを作りました

kintone APIのレコード操作を簡単に行えるライブラリを作ってみました。
github.com

kintone APIの公式ドキュメントは下記です。
kintone REST APIの共通仕様 – cybozu developer network

リクエストボディ

APIリクエストする際、Content-Typeに「application/json」を利用しているが
kintoneではRFC4627の形式に準拠する為、json_encodeで単純に変換すると
「不正なJSON文字列です」とエラーになってしまう事がありました。

配列ではなくオブジェクトとしてJSON変換されてしまう為です。

2016/01/10 の定期メンテナンスにおけるkintone API更新情報 Part1 – cybozu developer network


連想配列でなく、連番の場合は「array_values()」で配列であることを明確にすることで
この点は防ぐことができました。
PHPの配列を安全にJSONシリアライズする - Qiita

kintoneAPI開発での便利ツール

下記使うと楽だった。

HTTP Client Tool for kintone
https://developer.cybozu.io/hc/ja/articles/115001506986

よく分からないところがあれば、コミュニティで過去の質問を漁ってみたり
自分で質問するのもいいかも。

課題

CI

テストコードも、ローカルでのチェック用に申し訳程度に書いたけど
CIに対応しようと思ったら、アプリ生成→テストデータ追加→テスト→アプリ削除という手順を踏む必要がありそうで
非常にめんどくさそう。

ローカルでテスト実施できるだけでも、ちょっと直したときに
影響の有無をチェックできるので、テストコード書くと後が非常に楽だなと実感できたのはよかった。

CIでのAPIトークンってどこに置けばよいか

APIトークンとかbase64化したアカウントをどこに置くのがいいのか。
githubで公開したくないので、どういう風にすべきなんだろう。

調べてたら、下記方法がありそうです。

リクエストをモックに置き換えることで、APIトークンをコード内に含めない
https://github.com/hissy/kintone-php/blob/master/tests/ObjectTest.php

設定ファイル(APIトークン等)を入れたディレクトリをgit管理に含めない。
CIを行う際は、bitbucketなどのプライベートリポジトリを使って行うようにすべきなのだろうなと思います。
https://github.com/wataridori/chatwork-sdk/tree/master/tests

GASをES6で書く

Google Apps Scriptで、チャットワークAPIを使い
メッセージを送信するjsをES6で書いてみたいと思います。

ES6で書くための準備

やること

・GASのアップロードの自動化
・ES6→GAS用のJSに変換する

GASのアップロードの自動化

・初期化 / ダウンロード
 gapps init スクリプトID
 ※確認箇所:プロジェクトのプロパティ > スクリプト ID

・アップロード
 gapps upload

 ・アップロードできるが、ダウンロードははじめの「gapps init」のときのみ

・注意:

 ・アップロードできるのは Standalone Script のみでスプレッドシート
  ドキュメントなどにひもづいた Container-bound Script には対応していない
  (スプレッドシートから作成したGASで行うとgas initは出来るがアップロードで失敗する)

C:\node\gas>gapps upload
Pushing back up to Google Drive...
An error occured while running upload command: File not found: xxxxxx
Upload failed.

ES6→GAS用のJSに変換する

Google Apps Script を ES2015 で開発|株式会社CAリワード

上記ブログに記述されていたpackage.jsonを利用して「npm install」します。

{
  "devDependencies": {
    "browserify": "^13.1.1",
    "chai": "^3.5.0",
    "gasify": "^0.1.0",
    "mocha": "^3.2.0",
    "babel": "^6.5.2",
    "babel-core": "^6.7.4",
    "babel-preset-es2015": "^6.6.0",
    "babel-register": "^6.7.2",
    "gulp": "^3.9.1",
    "gulp-babel": "^6.1.2",
    "gulp-exec": "^2.1.2",
    "gulp-load-plugins": "^1.2.0",
    "gulp-plumber": "^1.1.0",
    "gulp-mocha": "^2.2.0",
    "babelify": "^5.0.5",
    "vinyl-source-stream": "^1.1.0"
  },
  "babel": {
    "presets": ["es2015"]
  }
}

「npm install」したらコードを書いて、下記コマンドでGAS用のソースに変換します。

browserify -t babelify -p gasify index.js -o gas.js


今回、chatworkAPIでメッセージを送信するプログラムを書きました。


chatworkAPIでメッセージを送信します。(ES6 / Google Apps Script)

twitterのトップでコンソールから自動ツイートする

chrome拡張で簡単に定型文をツイートさせようと思っていて、そのツイート部分の実装です。
twitterのホーム画面で、下記コードをchromeのコンソール等から実行すると定型文をツイートできます。

下記ソースは、はじめのやつが動きます。
2つ目は挙動が不安定です。

formタグを埋め込んで実行させる方はCSPの問題でエラーになるのと
成功しても実行結果のJSONファイルがローカルダウンロードされてしまいます。

単純に入力したいテキストを埋め込んでボタン押すようにしました。


CSPエラー:

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src https://connect.facebook.net https://cm.g.doubleclick.net https://ssl.google-analytics.com https://graph.facebook.com https://twitter.com 'unsafe-eval' https://*.twimg.com https://api.twitter.com https://analytics.twitter.com https://publish.twitter.com https://ton.twitter.com https://syndication.twitter.com https://www.google.com https://t.tellapart.com https://platform.twitter.com 'nonce-3fmPjUSbjydKKll2qfU3Hw==' https://www.google-analytics.com blob: 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-a3jrMYVXEEA6OiADmrxAYVqEyCuvciqKxYphw6Z0AiY='), or a nonce ('nonce-...') is required to enable inline execution.


twitter.comでコンソールからツイートを実行する

GoogleAnalyticsAPIを使って定期的にユーザサマリーをチャットに流してくれるライブラリを作った

目的

GoogleAnalyticsは、アクセスがほとんどなかろうと
無限に見ていられる悪魔のツールです。

その為、要点を定期的にチャットにぶん投げてくれる時間節約装置が欲しく作りました。

機能

googleAnalyticsAPIで、ユーザサマリー等を
自前のテンプレート形式で、チャットに自動通知してくれるライブラリを作りました。

まだテストも例外処理も使い方マニュアルも出来ておらず、とりあえず動いているレベルで拙いのですが。。。

github.com

下記のような感じでチャットに流れます。(chatwork)
アクセス数はゴミなのでスルーして下さい。。。

f:id:bz0:20171010005823p:plain

今後やるタスク

・テンプレートの追加
・例外処理
・使い方マニュアルの作成
・通知に、slack / メール通知を追加
・後入れで機能を足していったので
 コードが既にごちゃごちゃしている為、設計から考え直してみる

Google Analytics API(Management API)でビュー情報を取得する

何をしたのか

google analytics APIの「Core Reporting API」だと
サイト名やサイトURLが取れないようだったので、「Management API」でビュー情報からとるようにしてみた。

前提

Google Analytics のデータ構造はアカウント > プロパティ > ビューの構成になっている。
・ビューごとに、サービス アカウント IDのメルアドに権限の付与が必要
Google Analytics APIのライブラリ(SDK)がPHP 5.4以上なので、実行時のバージョンに注意する

準備

下記を読んで、APIキーの設定・composerでGoogle Analtics APIのライブラリをインストールしておく。

google analytics apiの利用方法
 https://qiita.com/zayarwinttun/items/90ef6979c644f262d0c4

google analytics apiの使い方
 https://syncer.jp/google-analytics-api-tutorial

・"google/apiclient": "1.*"でcomposerインストール
 "^2.0"とするとエラーが出てダウンロードできなかった為、1系を利用する。

Failed to download google/apiclient-services from dist: The process "unzip -qq -o '/var/www/html/gaApiClient/vendor/google/apiclient-services/cfe77a392d46e400cc90ece63d6dcc97' -d '/var/www/html/gaApiClient/vendor/composer/2223267b'" exceeded the timeout of 300 seconds.

注意

・ビュー情報を複数作成している場合、何故か1つしか取れなかった。
 今のところ未解決なので下記ソースを利用する場合は注意して下さい。

CSV読込して配列化 その2

CSV読み込むときに気を付けることをまとめてみました。

メモリを極力使わないようにする

ストリームを利用する

・大容量のCSVを読み込む際はストリームで「文字コード変換」を行う
 ストリームを利用すればメモリサイズを気にしなくてよくなる為

・ストリームフィルタを利用する際、iconvフィルタの利用は避ける
 iconvフィルタは不正なバイトが含まれていると全体を0バイトに変換してしまう
 http://d.hatena.ne.jp/hnw/20090317

CSVを一度に配列化してしまうと容量が大きい場合メモリを食いすぎる
 「 Stream_Filter_Mbstring」を使ってファイルを一行ずつ取得する
 http://nob-log.info/2012/04/17/stream_filter_mbstring/

エンコードの扱い

・文字エンコーディングの取り扱いはphpの各関数の実装に委ねられる

ロケールについて

・fgetcsv()はsetlocaleの影響を受ける
 ロケールhttps://wiki.archlinux.jp/index.php/%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB
 
 ・ロケールとは
   ロケールはOSが持っている多言語対応の仕組み。
  利用する言語 / 文字エンコードの設定を行うことが出来る。

 ・環境によりsetlocaleが効かない
  https://mgng.mugbum.info/1014
  ※Windows では setlocale(LC_ALL, 'ja_JP.UTF-8') は効かない

・setlocaleの挙動はOSのロケールの挙動に依存しており
 かつ大抵の環境の Shift_JISロケールは腐っている

ロケール設定はプロセス全体に影響する。
 マルチスレッドサーバで実行した場合、ほかのスレッドのロケール設定に影響を受ける

結論

・fgetcsv()はロケールに影響を受ける
 環境によってsetlocaleが効かない / マルチスレッドサーバで実行したときに他のスレッドの
 ロケール設定に影響を受けるかもしれない事に注意する。

・大容量のCSVの読込を行う場合は、メモリ対策の為にストリームを利用する

CSV読込して配列化

前提:
・読み込むCSVファイルはSJISであること
・PHP5.3で動作させることが前提(5.3以上でも動くはず)

微妙なので、書き直したい。


CSV(SJIS)読込クラスです。