命名って難しい

変数、関数、クラスなどなど実装より命名に毎回悩むタイプの人間による技術や趣味についてのメモ。

Google App ScriptでGmailの受信ボックスを自動でアーカイブしちゃう

Outlookメールでは一括処理というものがあり、n日後に○○するというようなルールが設定できます。 しかしGmailではできないのでGoogle App Scriptで組む事にしました。

Gmail自体はラベル機能が便利すぎるのでOutlookをメインにはしたくないんですよね。

スクリプトの流れ

以下の流れで実装しています。 - 検索クエリを作る - 検索クエリでメールスレッドを取得する - 取得したメールスレッドをアーカイブする

これをトリガー登録して定時実行させるだけです。(GASの定時実行については省略します)

なお、検索クエリについては以下のメールは除外しています。

1.☆つき ウェブブラウザのGmail以外で見るときに、アーカイブさせたくないメールをマークするために使います。

例えば - iPhoneのメールアプリ - フラグをつける - Thunderbird(デスクトップアプリ) - ☆マークをクリック

2. 重要とマークされている

Gmailに設定しているルールで重要にしたものは自分でアーカイブしたいので。

スクリプト

function gmailAutoarchive() {
 
  // 固定値。検索クエリと何日前のメールをアーカイブするか。
  const SearchQueryFormat = 'in:inbox -is:starred -is:important older:%s';
  const DelayDays = 14;

  // 指定日数前のメールを検索するクエリ文字列を作る
  var maxDate = new Date();
  maxDate.setDate(maxDate.getDate() - DelayDays);
  var maxDateStr = Utilities.formatDate(maxDate, 'JST', 'YYYY-MM-dd');
  var query = Utilities.formatString(SearchQueryFormat, maxDateStr);
  
  // クエリでメール検索してアーカイブ
  var threads = GmailApp.search(query);
  for (var i = 0; i < threads.length; i++) {
    threads[i].moveToArchive();
  }
  
}

注意点

受信ボックスのメールが多いと getInboxThreads がエラーになるようなので注意。その場合はページングをする必要があります。

参考リンク

クエリ作る support.google.com

日付のテキスト化 developers.google.com

メールを取得 developers.google.com

以上!

Windows10ProにAnaconda入れてコマンドラインでpythonと入れたらなぜかストアのPythonインストールページが開かれるのを直した。

経緯

自宅PCでpythonでも勉強しようかなと思っては

  1. 思い立ってpythonをAnacondaでインストールしてみる
  2. コマンドラインから python って入れたらストアが立ち上がる
  3. 再インストールしてみる
  4. 飽きて他の作業をしてしまう(そのためこの現象を忘れる)

ポンコツループを繰り返していました。

素直にググれという話なんですが、対処した方法をメモしておきます。

環境

項目 内容
エディション Windows 10 Pro
バージョン 1903
OSビルド 18362.778

対処方法

1. 設定からアプリを開く

f:id:NotShown:20200429143030p:plain
設定>アプリ

2. アプリからアプリ実行エイリアスを開く

※グレーの部分は隠しているだけです。

f:id:NotShown:20200429143417p:plain
アプリ>アプリ実行エイリアス

3. アプリ実行エイリアスから python, python3 のトグルをOFFにする。

※グレーの部分は隠しているだけです。

f:id:NotShown:20200429143309p:plain
pythonのトグルをOFFにする

思ったより簡単で設定からGUIで直せるのは良かったのですが、Windows Updateで勝手にエイリアスが追加されてしまうのは謎動作になってて嫌らしいですね。。。
素直にググるべきだった(2回目)

参考

superuser.com

以上。

Apple Musicのプレイリストを Spotifyにエクスポートした。

ネットでみかけたApple MusicのプレイリストをSpotifyに取り込むため、一部ブックマークレットと外部サービスを使って解決した流れをメモ。

前提

  • Apple Musicを登録していない。
  • Spotifyに登録している。

手順

1. プレイリストをテキスト形式に落とし込む

ブックマークレットを使います。
下記のブックマークレットを使うと今開いているページの曲目リストをテキストにしてダウンロードできます。

テキストの形式は以下。
Playlist Converterの仕様、Spotifyの検索結果の当たりやすさを考慮して、一部オリジナルから変えています。

  • 各行 [{{曲名}} - {{アーティスト名}}]の形式
  • 曲名の末尾につくfeat.系はカッコで閉じられた部分を削除することで除外。
  • アンパサンドを除外

ブックマークレット

javascript:(
    function () {
        const plName = document.querySelector(".product-header__title").innerText;
        const plMadeBy = document.querySelector(".product-header__identity").innerText;
        const csv =[];
        /* [曲名] - [アーティスト] の形式にする。*/
        /* 
          PlaylistConverter(https://www.playlist-converter.net/#/)の成功率を高めるため、下記2点の表現は削除する。
          ・曲名のかっこ書きで追記されるコラボレーションアーティスト(ラップなどでありがちな奴)
          ・アンパサンド
        */
        document.querySelectorAll("li.song-list-row").forEach(e=>{
            csv.push(
                e.querySelector(".tracklist-item__text__headline").innerText.replace(/\(.*\)/,"") + 
                ' - ' +
                e.querySelector(".table__row__link--secondary").innerText.replace(/&/g,"")
            ); 
        });
        /* ダウンロードする */
        const link = document.createElement("a");
        link.setAttribute('href','data:Application/octet-stream,' + encodeURIComponent(csv.join("\n")));
        link.setAttribute('download','am-playlist_' + plName + '-by-' + plMadeBy + ".txt" );
        link.click();
    }
)();

2. Playlist Converter にテキスト形式でデータを読み込ませる

https://www.playlist-converter.net/

  • Plain Text を選び、1.のテキストの中身をコピペする。
  • Convertボタンをクリックする。

f:id:NotShown:20200227184706p:plain
PlaylistConverter01

  • Convert to spotify をクリックする。(APIなどの連携が始まるので連携)

f:id:NotShown:20200227184603p:plain
PlaylistConverter02

  • 各曲を検索してSpotify対応にしてくれる。
  • 検索でヒットしないものは空白になる。
  • そのままプレイリストを作ってもいいし、URLリストを出力してSpotify上で貼り付けするのもよし。

f:id:NotShown:20200227202039p:plain
PlaylistConverter03

他にもApple Musicもアカウントあれば連携してくれるサービスとかあるっぽいんだけど、面倒なのでブックマークレットからのごり押しでの解決となりました。

以上。

PowerShell&Seleniumでネットショップの価格調査、初売りセールからの追加値下げを見たい。

新年あけました。 今年は福袋など買わず、ゆっくりと体を休めていました。

欲しい靴が某ECで初売りセールだったのですが、ネットでは「1/10前後で初売りセールよりまた安くする」というのを聞いたので PowerShellSeleniumを使って巡回してデータを集めて、かつ通知するようにしました。

結果として、自分の欲しい靴を安く手に入れることができてよかったのですが、普段業務で多用しているSeleniumだけでなく、Google Appsとの連携をしてみたので備忘のためにメモ。

要件

  • 1~2時間間隔くらいでデータ取得
  • データが時系列のグラフで見れる
  • 外出先から見れる(スマホ通知・メール)

こんな感じ。

概要

勢いで作ったので頭の中の整理も兼ねて Draw.io で作りました。

f:id:NotShown:20200115002258p:plain
ざっくりとした概要

今日はここまで、図を描くのにめっちゃ時間かかったので疲れた。。。 後日、実装系を書こう。 そんなボリュームないけれど。

sp_helpindexを全DB全テーブルに実行してインデックス情報を一覧にするクエリ

前提

検証用に本番機のデータベースをテスト環境に作りたくて、

スクリプトの生成」を使ってデータベース全体の作成クエリを作ったあと、データを本番機から流し込む、

という方法でやっていたら、インデックス作成クエリが出力されていなくてテストで失敗した。

本番機と比較して追加漏れを確認するために、このクエリを書いた。

クエリ

ざっくりと動作を説明すると sp_MSforeachdb と sp_MSforeachtable をネストし、sp_helpindex でインデックス情報を一時テーブルに格納し、選択する。

-- 一時テーブル 
CREATE TABLE #temp_index_info (a text, b text, c text)
CREATE TABLE #index_info (server_name text, db_name text, table_name text, index_name text, index_description text, index_keys text)

-- データベースは ! を使い、テーブルは ? を使うことで全DB全テーブルに対して処理をする。
EXEC sp_MSforeachdb @replacechar ='!', @command1='
    USE [!];
    EXEC sp_MSforeachtable ''
        INSERT #temp_index_info EXEC sp_helpindex ''''?'''';
        INSERT #index_info SELECT @@SERVERNAME, ''''!'''', ''''?'''', * FROM #temp_index_info;
        TRUNCATE TABLE #temp_index_info;
    ''
';
DROP TABLE #temp_index_info;

SELECT * FROM #index_info;
DROP TABLE #index_info;

学び

今回は sp_MSforeachdb , sp_MSforeachtableを初めて活用した。

めっちゃ便利。これからも使っていく。

あと、弊社内でもこういうインデックスの情報とかをまとめて簡単に参照できるウェブページが作れるといいね。

設定情報に加えて意図や目的をメモする欄とか入れたりして、DB自体の情報に対して説明を入れ込むことがしたい。

属人化も減るし、社内メンバーの理解度の底上げにもなると思う。

以上!

仮想マシンのWindows Server 2012 R2にSQL Server 2014 Expressをインストールするために必要な.NET Framework 3.5のインストールで苦しんだ結果「これで大丈夫?」って方法になった話。

タイトル長すぎる。

結論

仮想マシンでインストールメディアのないWindows Server 2012 R2 に SQL Server 2014 Expressをインストールする時に必要な .Net Framework をインストールするには、Windows Server 2012 R2 の評価版のISOからSxSフォルダを抽出してそこを指定してインストールする。

実際この方法で解決したんですけれど、大丈夫なんすかこの方法。 問題あれば誰かご指摘ください・・・。

経緯

自社テスト環境のために以下の環境を構築することになりました。

マシンの調達

そのため、まず仮想マシンを調達。

弊社はKDDIの閉域網WVSを使っており、その中で仮想マシンを調達できるKCPSを利用しています。

KCPSから仮想マシンを調達。

SQL Server 2014 Express の調達

以下からダウンロード

www.microsoft.com

SQL Server 2014 Expressのインストール

インストールを試したところ失敗。 .Net Framework 3.5 が必要なようです。

スクショ忘れた。

.Net Framework 3.5のインストール

.Net Framework 3.5 のインストール方法を調べたところ、以下の方法が見つかりました。

blogs.osdn.jp

が、それが失敗。原因がわからずググることに。

.NET Framework 3.5 インストール時のエラー: 0x800F0906、0x800F081F、0x800F0907 https://support.microsoft.com/ja-jp/help/2734782/net-framework-3-5-installation-error-0x800f0906-0x800f081f-0x800f0907

で、これも失敗。

Windows Updateなんども当てて最新にしようと、パッチを当てようとインストールはできませんでした。

評価版からのインストール

他の方法は「インストールメディアを指定してそれをソースとしてインストール」しかなく、インストール済の仮想マシンを調達したこの場合はインストールメディアもないので試せない。

インストールメディアが必要な理由はその中のSxSフォルダを参照するからなので、極端な話SxSフォルダさえあればいい。

Windows Server の評価版のISOから抜き出してSxSフォルダを使えばいい。

という発想のもと評価版をインストールしマウント。 SxSフォルダのみ抽出し、役割と機能の追加からやっと.Net Framework 3.5 をインストールすることができました。

SQL Serverのインストールも無事でき、環境構築が完了しました。

懸念

評価版のISOから抜き出してSxSフォルダを参照することに関して、ライセンス面での問題はあるのだろうか・・・

こういう懸念が出たとき、どうやって調べていくのがよいのか。

以上!

SQL Serverのセキュリティ保護可能なリソース、全部出す。

2019/09/18 追記

取得ということに焦点を当てて検索してコピペで作ったけれど、今後は sys.database_permissions をきっちり見ていく必要があるなと思った。今回は許可のみ(現在のシステムがそうなっている)で考えていたけれど、拒否もあれば permission stateも表示すると正確に把握できる。

docs.microsoft.com


引き継いだシステムの検証用データベースの構築をしたのですが、セキュリティ保護可能なリソースの設定漏れが発生したので再発防止のため、表題のクエリを作成した。

SSMSで一つづつポチポチプロパティを変更して設定していったため作業漏れが発生したので、まず一覧がほしいと思ったのでそこまで。 将来的には権限を設定するクエリも作成しておいて、検証用DBの作成が楽になるといいな。

日英表現違いに注意

URLとか英語で読むにしたら分かるんですが、セキュリティ保護可能なリソースは英語で securables です。

docs.microsoft.com

securables でググるだけでもかなり情報へのアクセスしやすさが変わりました。

クエリ

一時テーブルはめっちゃ適当です。

CREATE TABLE #secuarables_alldb (
    server_name text,
    database_name text,
    object_name text,
    user_name text,
    permission_name text
);

EXEC sp_MSforeachdb '
USE ?;

INSERT INTO #secuarables_alldb
SELECT
   @@servername as server_name, ''?'' AS database_name, OBJECT_NAME(major_id) as object_name, USER_NAME(grantee_principal_id) as user_name, permission_name
FROM
    sys.database_permissions p
WHERE
    p.class = 1 AND
    OBJECTPROPERTY(major_id, ''IsMSSHipped'') = 0
ORDER BY
    OBJECT_NAME(major_id), USER_NAME(grantee_principal_id), permission_name
';


select * FROM #secuarables_alldb;
DROP table #secuarables_alldb;

参考

sp_MSforeachdb

めっちゃ便利だった。こんなものがあるとは。。。
勉強の過程でこういうのってどうやってたどり着くんでしょうね。

blog.engineer-memo.com

Securables の取得

stackoverflow.com