Better ATND

ATNDをより便利にする

  1. // ==UserScript==
  2. // @name Better ATND
  3. // @namespace http://efcl.info/
  4. // @description ATNDをより便利にする
  5. // @include http://atnd.org/events/*
  6. // @include https://atnd.org/events/*
  7. // @version 0.2.0.20140518104253
  8. // @grant GM_log
  9. // @grant GM_xmlhttpRequest
  10. // ==/UserScript==
  11. /* TEST PAGE
  12. http://atnd.org/events/13389
  13. http://atnd.org/events/10996
  14. */
  15. var DEBUG = false;
  16. function log(m) {
  17. console.log(arguments);
  18. }
  19. var atndGM = {};
  20. atndGM.eventID = window.location.pathname.split("/").pop();
  21. (function () {
  22. // ATND APIからイベント情報取得
  23. function getEventJSON(eventID, callback) {
  24. if (typeof atndGM[atndGM.eventID] !== 'undefined') {
  25. callback(atndGM[atndGM.eventID]);
  26. } else {
  27. var endpoint = "http://api.atnd.org/events/?event_id=" + eventID + "&format=json";
  28. GM_xmlhttpRequest({
  29. method: "GET",
  30. url: endpoint,
  31. onload: function (res) {
  32. var json = JSON.parse(res.responseText);
  33. DEBUG && log(res.statusText, json);
  34. atndGM[atndGM.eventID] = json;// キャッシュしておく
  35. callback(json);
  36. },
  37. onerror: function (res) {
  38. GM_log(res.statusText + " : " + res.responseText);
  39. }
  40. });
  41. }
  42. }
  43.  
  44. // 緯度経度情報の取得
  45. function getGeoinfo(json) {
  46. var event = json.events[0].event;
  47. var lon = event.lon,
  48. lat = event.lat;
  49. DEBUG && log('lon' + lon, 'lat' + lat);
  50. if ((lon && lat)
  51. && (parseFloat(lon) != 0.0 && parseFloat(lat) != 0.0)) {
  52. // 緯度経度情報が取得できた場合は最寄り駅を取得する
  53. return {
  54. 'lon': lon,
  55. 'lat': lat
  56. };
  57. }
  58. }
  59.  
  60. // 緯度経度から最寄り駅情報を取得
  61. function getNearsideStation(geo, callback) {
  62. var endpoint = "http://map.simpleapi.net/stationapi?x=" + String(geo.lon) + "&y=" + String(geo.lat) + "&output=json";
  63. var count = 0;
  64. GM_xmlhttpRequest({
  65. method: "GET",
  66. url: endpoint,
  67. onload: function (res) {
  68. var json = JSON.parse(res.responseText),
  69. resultHTML = document.createDocumentFragment();
  70. var dl = document.createElement('dl');
  71. dl.setAttribute('class', "clearfix station-info");
  72. DEBUG && log("near Stations JSON", json);
  73. for (var i = 0, len = json.length; i < len; i++) {
  74. var name = json[i].name;
  75. var line = json[i].line;
  76. var distance = json[i].distanceKm || json[i].distanceM;
  77. var traveltime = json[i].traveltime;
  78. var stationInfo = line + "/" + name + "/" + distance + "/" + traveltime;
  79.  
  80. var dt = document.createElement('dt');
  81. dt.innerHTML = "最寄り駅 / ST:";
  82. var dd = document.createElement('dd');
  83. dd.appendChild(document.createTextNode(stationInfo));
  84. dl.appendChild(dt);
  85. dl.appendChild(dd);
  86. }
  87. resultHTML.appendChild(dl);
  88. DEBUG && log("resultHTML", resultHTML);
  89. callback(resultHTML);
  90. },
  91. onerror: function (res) {
  92. GM_log(res.statusText + " : " + res.responseText);
  93. }
  94. });
  95.  
  96. }
  97.  
  98. function getStationHTML(callback) {
  99. getEventJSON(atndGM.eventID, function (res) {
  100. atndGM.st.geo = getGeoinfo(res);
  101. if (atndGM.st.geo) {
  102. getNearsideStation(atndGM.st.geo, function (resHTML) {
  103. DEBUG && log("getStationHTML", resHTML);
  104. callback(resHTML);
  105. });
  106. } else {
  107. DEBUG && log("getStationHTML : GEO INFO doesn't exist");
  108. callback();
  109. }
  110. });
  111. }
  112.  
  113.  
  114. atndGM.st = {
  115. 'getEventJSON': getEventJSON,
  116. 'getNearsideStation': getNearsideStation,
  117. 'getStationHTML': getStationHTML
  118. };
  119. })();
  120. (function gCal() {
  121. function formatToUTCDate(jstDateTime) {
  122. if (!jstDateTime) {
  123. return;
  124. }
  125. var dateTime = jstDateTime.replace(/[-,:]/g, "").replace(/.....$/, "");
  126. var jstDate = Number(dateTime.slice(0, 8));
  127. var jstTime = Number(dateTime.slice(9, 15));
  128. var utcDate;
  129. if (jstTime < 90000) {
  130. utcDate = jstDate - 1;
  131. } else {
  132. utcDate = jstDate;
  133. }
  134. var utcTime = String((jstTime + 240000 - 90000) % 240000);
  135. utcTime = utcTime.length == 6 ? utcTime : '0' + utcTime;
  136. return utcDate + 'T' + utcTime + 'Z';
  137. }
  138.  
  139. function createCalendarLink(json) {
  140. json = json || atndGM[atndGM.eventID] || atndGM.st.getEventJSON(createCalendarLink);
  141. var event = json.events[0].event;// イベントの情報が入ってる
  142. var descrition = location.href + '\n_' + document.getElementById("post-body").textContent.trim();// API経由だと記法が入ってしまう
  143. if ("catch" in event) {
  144. descrition = event["catch"] + "\n" + descrition;// キャッチを追加する
  145. }
  146. var description = encodeURIComponent((descrition.length < 300) ? // 文字数が多いとRequest-URI Too Largeになる
  147. descrition : descrition.substring(0, 100) + '...');
  148. var title = encodeURIComponent(event.title),
  149. started_at = formatToUTCDate(event.started_at || ""),
  150. ended_at = formatToUTCDate(event.ended_at || ""),
  151. address = encodeURIComponent(event.address || "");
  152.  
  153. var dates = "&dates=" + started_at + "/"
  154. if (ended_at) {
  155. dates += ended_at;
  156. } else {
  157. dates += started_at;// ないなら開始時間と同じ
  158. }
  159. // カレンダーリンクを生成
  160. var link = document.createElement('a');
  161. link.innerHTML = "<img src='http://www.google.com/calendar/images/ext/gc_button1_ja.gif' border=0></a>";
  162. link.setAttribute('href',
  163. 'https://www.google.com/calendar/event?action=TEMPLATE&text=' + title
  164. + dates
  165. + "&details=" + description + "&location=" + address + "&trp=false&sprop=website:atnd.org&sprop;=name:ATND");
  166. return link;
  167. }
  168.  
  169. atndGM.gCal = {
  170. 'createCalendarLink': createCalendarLink
  171. }
  172. })();
  173. (function main() {
  174. var insertArea = document.querySelector('#events-show > div.main');
  175. var stationArea = insertArea.querySelector('div.events-show-info');
  176. var mapArea = insertArea.querySelector('div.events-show-map');
  177. atndGM.st.getStationHTML(function (stationHTML) {
  178. if (typeof stationHTML !== 'undefined') {
  179. stationArea.appendChild(stationHTML);
  180. var stationMapImg = document.createElement("img");
  181. stationMapImg.src = "http://map.simpleapi.net/stationmap?x=" + atndGM.st.geo.lon + "&y=" + atndGM.st.geo.lat;
  182. mapArea.appendChild(stationMapImg);
  183. }
  184. // Google Calendar
  185. var title_ul = document.querySelector('div.title-btn > ul');
  186. var link = atndGM.gCal.createCalendarLink();
  187. var li = document.createElement("li");
  188. li.appendChild(link);
  189. title_ul.appendChild(li);
  190. });
  191.  
  192. })();
  193.