MHQ ago

Show timestamps

当前为 2019-03-31 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name MHQ ago
  3. // @namespace none
  4. // @version 2019.03.31.1242
  5. // @description Show timestamps
  6. // @supportURL https://Discord.me/TheShoeStore
  7. // @author technical13
  8. // @match https://www.munzee.com/m/*
  9. // @match https://www.munzee.com/referral/*
  10. // @grant none
  11. // ==/UserScript==
  12. // jshint esversion: 6
  13.  
  14. var isDebug = false;
  15. var intVerbosity = 0;
  16. const ver = '2019.03.31.1242';
  17. const scriptName = 'MHQ ago v' + ver;
  18.  
  19. function log( intV, strConsole, strLog, ...arrArgs ) {
  20. if ( strConsole === undefined ) { strConsole = 'log'; }
  21. if ( strLog === undefined ) { strLog = '%o'; }
  22. if ( intVerbosity >= intV && ( strConsole === 'groupEnd' ) ) { console[ strConsole ](); }
  23. if ( intV === 0 || ( isDebug && intVerbosity >= intV ) ) { console[ strConsole ]( '[%i]: %s: ' + strLog, intV, scriptName, ...arrArgs ); }
  24. }
  25.  
  26. function countDown( intRawSeconds ) {
  27. var intSeconds = parseInt( intRawSeconds );
  28. var intHours = Math.floor( intSeconds / 3600 );
  29. intSeconds = intSeconds - ( intHours * 3600 );
  30. var intMinutes = Math.floor( intSeconds / 60 );
  31. intSeconds = intSeconds - ( intMinutes * 60 );
  32. var strCountDown = ( intHours > 0 ? intHours.toLocaleString() +
  33. ' hour' + ( intHours === 1 ? '' : 's' ) : '' ) +
  34. ( intMinutes > 0 ? ( intHours > 0 ? ', ' : '' ) +
  35. intMinutes.toLocaleString() + ' minute' + ( intMinutes === 1 ? '' : 's' ) : '' ) +
  36. ( intSeconds > 0 ? ( intHours > 0 || intMinutes > 0 ? ', ' : '' ) +
  37. intSeconds.toLocaleString() + ' second' + ( intSeconds === 1 ? '' : 's' ) : '' );
  38.  
  39. log( 4, 'log', 'countDown( %i ) is returning: %s', intRawSeconds, strCountDown );
  40. return strCountDown;
  41. }
  42.  
  43. const intParamsStart = ( document.URL.indexOf( '?' ) + 1 );
  44. const strParams = document.URL.substr( intParamsStart );
  45. const arrParamSets = strParams.split( '&' );
  46. var objParams = {};
  47. arrParamSets.forEach( function( strParam ) {
  48. let arrParam = strParam.split( '=' );
  49. let strParamName = ( arrParam[ 0 ].toLowerCase() || '' );
  50. if ( strParamName === 'verbosity' ) {
  51. isDebug = true;
  52. intVerbosity = ( arrParam[ 1 ] ? ( parseInt( arrParam[ 1 ] ) < 0 ? 0 : ( parseInt( arrParam[ 1 ] ) > 9 ? 9 : parseInt( arrParam[ 1 ] ) ) ) : 9 );
  53. } else if ( strParamName === 'debug' ) {
  54. isDebug = toBoolean( arrParam[ 1 ] );
  55. intVerbosity = 1;
  56. }
  57. } );
  58.  
  59. log( 1, 'warn', 'Debug mode is on with verbosity level: %o', intVerbosity );
  60. log( 1, 'groupCollapsed', 'Verbosity options: (click to expand)' );
  61. log( 1, 'log', '1) Summary\n2) Parameters retrieved from URL\n3) Variables set to objParams\n4) Function returns\n9) ALL debugging info and this notice.' );
  62. log( 1, 'groupEnd' );
  63.  
  64. function toBoolean( val ) {
  65. const arrTrue = [ undefined, null, '', true, 'true', 1, '1', 'on', 'yes' ];
  66. val = ( typeof( val ) === 'string' ? val.toLowerCase() : val );
  67.  
  68. log( 4, 'log', 'toBoolean() is returning: %o', ( arrTrue.indexOf( val ) !== -1 ? true : false ) );
  69. return ( arrTrue.indexOf( val ) !== -1 ? true : false );
  70. }
  71.  
  72. const objFullTimeStringHQ = {
  73. year: 'numeric', month: 'long', day: 'numeric',
  74. hour: 'numeric', minute: 'numeric', second: 'numeric',
  75. timeZone: 'America/Chicago', timeZoneName: 'short', hour12: false };
  76. const objShorTimeStringHQ = {
  77. year: 'numeric', month: 'short', day: 'numeric',
  78. hour: 'numeric', minute: 'numeric', second: 'numeric',
  79. timeZone: 'America/Chicago', hour12: false };
  80.  
  81. const address = document.URL.replace( /https?:\/\/www\.munzee\.com\/m\//i, '' ).split( '/' );
  82. const userName = ( address[ 0 ] || undefined );
  83. const subPage = ( address[ 1 ] || undefined );
  84. const subSubPage = ( address[ 2 ] || undefined );
  85. log( 1, 'info', 'userName = %s\tsubPage = %s\tsubSubPage = %s', userName, subPage, subSubPage );
  86.  
  87. const rxpMins = RegExp( '\\d+ minutes ago', 'i' );
  88. const rxpHrs = RegExp( '\\d+ hours ago', 'i' );
  89. const rxpDays = RegExp( '\\d+ days ago', 'i' );
  90.  
  91. ( function() {
  92. 'use strict';
  93. log( 0, 'info', 'Script loaded.' );
  94.  
  95. $( '.expires-at' ).each( function( i, elem ) {
  96. var objExpires = new Date( $( elem ).attr( 'title' ) );
  97. var intSecondsUntilExpires = Math.floor( ( objExpires.valueOf() - ( new Date() ).valueOf() ) / 1000 );
  98. var strNewExpires = objExpires.toLocaleDateString( 'en-US', objShorTimeStringHQ ) +
  99. ' (<span id="expires-countdown">' + countDown( intSecondsUntilExpires ) + '</span>)</span>';
  100. var objNudgeable = new Date( $( elem ).attr( 'title' ) );
  101. objNudgeable = new Date( objNudgeable.setHours( objNudgeable.getHours() - 9 ) );
  102. var intSecondsUntilNudge = Math.floor( ( objNudgeable.valueOf() - ( new Date() ).valueOf() ) / 1000 );
  103. var strNewNudge = '';
  104. if ( intSecondsUntilNudge > 0 ) {
  105. strNewNudge = '<br /><span class="nudge-at" data-nudge-at="' + objNudgeable.valueOf() +
  106. '" title="' + objNudgeable.toISOString() + '">Nudgeable ' +
  107. objNudgeable.toLocaleDateString( 'en-US', objShorTimeStringHQ ) + ' (<span id="nudge-countdown">' +
  108. countDown( intSecondsUntilNudge ) + '</span>)';
  109. }
  110. $( elem ).html( strNewExpires + strNewNudge );
  111. setInterval( function() {
  112. intSecondsUntilNudge = Math.floor( ( objNudgeable.valueOf() - ( new Date() ).valueOf() ) / 1000 );
  113. if ( intSecondsUntilNudge > 0 ) {
  114. $( 'span#nudge-countdown' ).text( countDown( intSecondsUntilNudge ) );
  115. } else {
  116. $( 'span.nudge-at' ).remove();
  117. }
  118. intSecondsUntilExpires = Math.floor( ( objExpires.valueOf() - ( new Date() ).valueOf() ) / 1000 );
  119. if ( intSecondsUntilExpires > 0 ) {
  120. $( 'span#expires-countdown' ).text( countDown( intSecondsUntilExpires ) );
  121. } else {
  122. location.reload();
  123. }
  124. }, 1000 );
  125. } );
  126.  
  127. $( '.deployed-at' ).each( function( i, elem ) {
  128. var strDeployed = new Date( $( elem ).attr( 'data-deployed-at' ) );
  129. var strRawAgo = $( elem ).text();
  130. var intSecondsAgo = Math.round( ( ( new Date() ).valueOf() - strDeployed.valueOf() ) / 1000 );
  131. if ( strRawAgo === 'seconds ago' || strRawAgo === 'a minute ago' ) {
  132. strRawAgo = intSecondsAgo + '&nbsp;seconds&nbsp;ago';
  133. } else if ( rxpMins.test( strRawAgo ) || strRawAgo === 'an hour ago' || strRawAgo === '2 hours ago' ) {
  134. strRawAgo = ( Math.round( ( intSecondsAgo / 60 ) * 10 ) / 10 ) + '&nbsp;minutes&nbsp;ago';
  135. } else if ( rxpHrs.test( strRawAgo ) || strRawAgo === 'a day ago' ) {
  136. strRawAgo = ( Math.round( ( intSecondsAgo / 60 / 60 ) * 100 ) / 100 ) + '&nbsp;hours&nbsp;ago';
  137. } else if ( rxpDays.test( strRawAgo ) ) {
  138. strRawAgo = ( Math.round( ( intSecondsAgo / 60 / 60 / 24 ) * 100 ) / 100 ) + '&nbsp;days&nbsp;ago';
  139. } else {
  140. strRawAgo = strRawAgo.replace( ' ', '&nbsp;' );
  141. }
  142. switch( subPage ) {
  143. case 'archived' :
  144. case 'captures' :
  145. case 'deploys' :
  146. $( elem ).html( strRawAgo + '<br />' + strDeployed.toLocaleDateString( 'en-US', objShorTimeStringHQ ) );
  147. break;
  148. case 'socials' :
  149. if ( subSubPage === 'own' ) {
  150. $( elem ).html( strRawAgo + '<br />' + strDeployed.toLocaleDateString( 'en-US', objShorTimeStringHQ ) );
  151. }
  152. break;
  153. case 'kennel' :
  154. if ( subSubPage === 'transported' ) {
  155. $( elem ).html( strRawAgo + '<br />' + strDeployed.toLocaleDateString( 'en-US', objFullTimeStringHQ ) );
  156. }
  157. break;
  158. case 'blast' :
  159. case 'feed' :
  160. default:
  161. if ( !isNaN( subSubPage ) ) {
  162. $( elem ).html( strRawAgo + '<br />' + strDeployed.toLocaleDateString( 'en-US', objFullTimeStringHQ ) );
  163. } else {
  164. $( elem ).html( strDeployed.toLocaleDateString( 'en-US', objFullTimeStringHQ ) + ' &shy;(' + strRawAgo + ')' );
  165. }
  166. }
  167. } );
  168.  
  169. $( '.captured-at' ).each( function( i, elem ) {
  170. var strCaptured = new Date( $( elem ).attr( 'data-captured-at' ) );
  171. var strRawAgo = $( elem ).text();
  172. var intSecondsAgo = Math.round( ( ( new Date() ).valueOf() - strCaptured.valueOf() ) / 1000 );
  173. if ( strRawAgo === 'seconds ago' || strRawAgo === 'a minute ago' ) {
  174. strRawAgo = intSecondsAgo + '&nbsp;seconds&nbsp;ago';
  175. } else if ( rxpMins.test( strRawAgo ) || strRawAgo === 'an hour ago' || strRawAgo === '2 hours ago' ) {
  176. strRawAgo = ( Math.round( ( intSecondsAgo / 60 ) * 10 ) / 10 ) + '&nbsp;minutes&nbsp;ago';
  177. } else if ( rxpHrs.test( strRawAgo ) || strRawAgo === 'a day ago' ) {
  178. strRawAgo = ( Math.round( ( intSecondsAgo / 60 / 60 ) * 100 ) / 100 ) + '&nbsp;hours&nbsp;ago';
  179. } else if ( rxpDays.test( strRawAgo ) ) {
  180. strRawAgo = ( Math.round( ( intSecondsAgo / 60 / 60 / 24 ) * 100 ) / 100 ) + '&nbsp;days&nbsp;ago';
  181. } else {
  182. strRawAgo = strRawAgo.replace( ' ', '&nbsp;' );
  183. }
  184. switch( subPage ) {
  185. case 'archived' :
  186. case 'captures' :
  187. case 'deploys' :
  188. $( elem ).html( strRawAgo + '<br />' + strCaptured.toLocaleDateString( 'en-US', objShorTimeStringHQ ) );
  189. break;
  190. case 'socials' :
  191. if ( subSubPage === 'own' ) {
  192. $( elem ).html( strRawAgo + '<br />' + strCaptured.toLocaleDateString( 'en-US', objShorTimeStringHQ ) );
  193. }
  194. break;
  195. case 'kennel' :
  196. if ( subSubPage === 'transported' ) {
  197. $( elem ).html( strRawAgo + '<br />' + strCaptured.toLocaleDateString( 'en-US', objFullTimeStringHQ ) );
  198. }
  199. break;
  200. case 'blast' :
  201. case 'feed' :
  202. default:
  203. $( elem ).html( strCaptured.toLocaleDateString( 'en-US', objFullTimeStringHQ ) + ' &shy;(' + strRawAgo + ')' );
  204. }
  205. } );
  206.  
  207. $( '.blasted-at' ).each( function( i, elem ) {
  208. var strBlasted = new Date( $( elem ).attr( 'data-blasted-at' ) );
  209. $( elem ).append( '<p>' + strBlasted.toLocaleDateString( 'en-US', objFullTimeStringHQ ) + '</p>' );
  210. } );
  211.  
  212. $( '.wrote-at' ).each( function( i, elem ) {
  213. var strWrote = new Date( $( elem ).attr( 'data-wrote-at' ) );
  214. var strRawAgo = $( elem ).text();
  215. var intSecondsAgo = Math.round( ( ( new Date() ).valueOf() - strWrote.valueOf() ) / 1000 );
  216. if ( strRawAgo === 'seconds ago' || strRawAgo === 'a minute ago' ) {
  217. strRawAgo = intSecondsAgo + '&nbsp;seconds&nbsp;ago';
  218. } else if ( rxpMins.test( strRawAgo ) || strRawAgo === 'an hour ago' || strRawAgo === '2 hours ago' ) {
  219. strRawAgo = ( Math.round( ( intSecondsAgo / 60 ) * 10 ) / 10 ) + '&nbsp;minutes&nbsp;ago';
  220. } else if ( rxpHrs.test( strRawAgo ) || strRawAgo === 'a day ago' ) {
  221. strRawAgo = ( Math.round( ( intSecondsAgo / 60 / 60 ) * 100 ) / 100 ) + '&nbsp;hours&nbsp;ago';
  222. } else if ( rxpDays.test( strRawAgo ) ) {
  223. strRawAgo = ( Math.round( ( intSecondsAgo / 60 / 60 / 24 ) * 100 ) / 100 ) + '&nbsp;days&nbsp;ago';
  224. } else {
  225. strRawAgo = strRawAgo.replace( ' ', '&nbsp;' );
  226. }
  227. $( elem ).html( strRawAgo );
  228. } );
  229. } )();