// ==UserScript== // @name backlog2slimtimer // @namespace http://d.hatena.ne.jp/ikikko/ // @description Backlogの課題をSlimTimerにエクスポートします // @include https://*.backlog.jp/find/* // @include https://*.backlog.jp/FindIssue.action?* // @require http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js // @resource stIcon http://slimtimer.com/favicon.ico // @author ikikko // @version 0.0.1 // ==/UserScript== jQuery.noConflict(); jQuery(function($) { // ----------------------------------------------[Variable] var BASE_URL = 'http://slimtimer.com/users'; var email = getStEmail(); var password = getStPassword(); var apiKey = getStApiKey(); var accessToken; var userId; // ----------------------------------------------[Main] appendCheckbox(); // ----------------------------------------------[Function] /** SlimTimerのログイン情報(Email)を取得する */ // TODO about:configじゃなくて、右クリックで再設定できるようにしてもいいかも function getStEmail() { var email = GM_getValue('SLIMTIMER_EMAIL'); if (typeof email === 'undefined' || email == '') { email = prompt("What is Your SLIMTIMER's E-mail address?", ''); if (email) GM_setValue('SLIMTIMER_EMAIL', email); else throw 'Unable to get SLIMTIMER account\'s E-mail address.'; } return email; } /** SlimTimerのログイン情報(Password)を取得する */ function getStPassword() { var password = GM_getValue('SLIMTIMER_PASSWORD'); if (typeof password === 'undefined' || password == '') { password = prompt("What is Your SLIMTIMER's Password?", ''); if (password) GM_setValue('SLIMTIMER_PASSWORD', password); else throw 'Unable to get SLIMTIMER account\'s password.'; } return password; } /** SlimTimerのAPI Keyを取得する */ function getStApiKey() { var apiKey = GM_getValue('SLIMTIMER_API_KEY'); if (typeof apiKey === 'undefined' || apiKey == '') { apiKey = prompt("What is Your SLIMTIMER's API Key?", ''); if (apiKey) { GM_setValue('SLIMTIMER_API_KEY', apiKey); } else { throw 'Unable to get SLIMTIMER\'s api_key.'; } } return apiKey; } /** SlimTimer登録時に設定するタグを取得する */ function getStTag() { var SLIMTIMER_DEFAULT_TAG = 'BACKLOG'; var tag = GM_getValue('SLIMTIMER_TAG'); if (typeof tag === 'undefined' || tag == '') { tag = SLIMTIMER_DEFAULT_TAG; GM_setValue('SLIMTIMER_TAG', SLIMTIMER_DEFAULT_TAG); } return tag; } /** (エクスポートする課題を選択するための)チェックボックスを追加する */ function appendCheckbox() { // 追加要素の作成 var icon = $('').addClass('backlog2slimtimer').append( ""); var checkbox = $('').addClass('backlog2slimtimer').append( ""); // 要素を既存DOM内に追加 $('#issues-table th.first').after(icon); $('#issues-table td.chevron').after(checkbox); // クリック時イベントをバインド $('#issues-table th input').click(function(event) { getUserAuthAndExportIssues(); }); $('#issues-table td.backlog2slimtimer').click(function(event) { event.stopPropagation(); }); } /** 認証情報を取得した後、課題をエクスポートする */ function getUserAuthAndExportIssues() { // TODO パラメータ組み立てを関数化 or 外部ライブラリの活用 GM_xmlhttpRequest( { method : 'POST', url : BASE_URL + '/' + 'token', headers : { 'Accept' : 'application/xml', 'Content-Type' : 'application/x-www-form-urlencoded' }, data : 'api_key' + '=' + apiKey + '&' + 'user[email]' + '=' + encodeURIComponent(email) + '&' + 'user[password]' + '=' + encodeURIComponent(password), onload : function(response) { var user = $(response.responseText); accessToken = user.find('access-token').text(); userId = user.find('user-id').text(); exportIssues(); }, onerror : function() { // TODO 失敗時のエラーハンドル } }); } /** チェックされた課題を、(キー・件名)を組にしてエクスポートする */ function exportIssues() { $('#issues-table td input:checked').parents('tr').each(function() { var key = $.trim($(this).children('.key').text()); var title = $.trim($(this).children('.title').text()); createTask('[' + key + ']' + title); }); } /** タスクを作成する */ function createTask(taskName) { GM_xmlhttpRequest( { method : 'POST', url : BASE_URL + '/' + userId + '/' + 'tasks', headers : { 'Accept' : 'application/json', 'Content-Type' : 'application/x-www-form-urlencoded' }, data : 'api_key' + '=' + apiKey + '&' + 'access_token' + '=' + accessToken + '&' + 'task[name]' + '=' + encodeURIComponent(taskName) + '&' + 'task[tags]' + '=' + getStTag(), onload : function(response) { // TODO 結果を分かりやすい形で表示する GM_log(response.responseText); }, onerror : function(response) { // TODO 結果を分かりやすい形で表示する } }); } });