S1 User Tagging

给stage1st加上标记用户/屏蔽用户帖子/修改用户帖子颜色/保存用户帖子

  1. // ==UserScript==
  2. // @name S1 User Tagging
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description 给stage1st加上标记用户/屏蔽用户帖子/修改用户帖子颜色/保存用户帖子
  6. // @author Hibino
  7. // @include http*://bbs.saraba1st.com/*
  8. // @include http*://www.saraba1st.com/*
  9. // @require https://code.jquery.com/jquery-3.1.1.min.js
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant GM_addStyle
  13. // ==/UserScript==
  14.  
  15.  
  16. (function() {
  17. 'use strict';
  18.  
  19. var DATA_FILE = "s1_user_tags";
  20. var POST_URL = "/2b/forum.php?mod=redirect&goto=findpost&pid=";
  21. var HTML_USERNAME =
  22. '<div id="tgut_pid_PID" class="tgut" data-uid="UID" data-pid="PID" >' +
  23. '<div class="t">S1UT</div>' +
  24. '<div class="m">' +
  25. '<div class="tag">标签:<input class="in" type="text" name="tag" value="TAG" /></div>' +
  26. '<div class="colors">' +
  27. '<div class="c c1 f"></div>' +
  28. '<div class="c c2"></div>' +
  29. '<div class="c c3"></div>' +
  30. '<div class="c c4"></div>' +
  31. '<div class="c c5 f"></div>' +
  32. '<div class="c c6"></div>' +
  33. '<div class="c c7"></div>' +
  34. '<div class="c c8"></div>' +
  35. '<div class="c c9 f"></div>' +
  36. '<div class="c c10"></div>' +
  37. '<div class="c c11"></div>' +
  38. '<div class="c c12"></div>' +
  39. '<div class="tgut-clear"></div></div>' +
  40. '<div class="clor">颜色:<input class="in" type="text" name="color" value="COLOR" /></div>' +
  41. '<div class="remv"><label><input type="checkbox" name="remove_post" value="1" REMOVE_POST>隐藏该用户帖子</label></div>' +
  42. '<button class="but but-save-tag" type="button" name="dummy" value="Save" data-pid="PID">保存</button>' +
  43. '<hr>' +
  44. '<button class="but but-save-post" type="button" name="dummy" value="Save Post" data-pid="PID" data-uid="UID">保存帖子</button>' +
  45. '&nbsp;&nbsp;&nbsp;&nbsp;' +
  46. '<button class="but but-view-posts" type="button" name="dummy" value="Save Post" data-pid="PID" data-uid="UID">查看帖子</button>' +
  47. '</div>' +
  48. '</div>';
  49. var HTML_TAG = '<div class="tgut-tag">TAG</div>';
  50. var HTML_MSG = '<div id="tgut_msg" class="tgut-msg"></div>';
  51. var HTML_POPUP =
  52. '<div class="tgut-page-cover" id="tgut_page_cover"></div>' +
  53. '<div class="tgut-popup" id="tgut_popup">' +
  54. '<div class="tt"><div class="f-l" id="tgut_popup_title">&nbsp;</div><div class="f-r cls" id="tgut_popup_close"><a>X</a></div><div class="tgut-clear"></div></div>' +
  55. '<div class="ct" id="tgut_popup_content"></div>' +
  56. '</div>';
  57. var HTML_SETTINGS =
  58. '<div id="tgut_settings" class="tgut-sett">'+
  59. '<div class="b"><button class="but but-clean" type="button" name="dummy" value="Clean">清除数据</button>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' +
  60. '<button class="but but-export" type="button" name="dummy" value="Export">导出数据</button>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' +
  61. '<button class="but but-import" type="button" name="dummy" value="Import">导入数据</button></div>'+
  62. '<div class="t">导出时请保存下框的所有文本数据。导入时请把文本数据复制到下框然后点击“导入数据”按钮' +
  63. '<br /><textarea id="tgut_data_text" class="txa" name="dummy"></textarea></div>' +
  64. '</div>';
  65.  
  66. GM_addStyle(
  67. `
  68. .tgut-clear{
  69. clear: both;
  70. }
  71. .tgut-blur{
  72. filter: blur(20px);
  73. }
  74. .tgut{
  75. top: 0;
  76. right: 0;
  77. position: absolute;
  78. font-weight: normal;
  79. }
  80. .tgut:hover{
  81. }
  82. .tgut-msg{
  83. display: none;
  84. position: fixed;
  85. width: 300px;
  86. padding: 5px 10px;
  87. top: 0;
  88. left: 50%;
  89. margin-left: -150px;
  90. color: #ffffff;
  91. text-align: center;
  92. background: #0033cc;
  93. z-index: 300;
  94. }
  95. .tgut .t{
  96. display: block;
  97. padding: 2px 5px;
  98. color: #ffffff;
  99. background: #006cc2;
  100. cursor: pointer;
  101. }
  102. .tgut .m{
  103. display: none;
  104. position: absolute;
  105. width: 145px;
  106. right: 0;
  107. padding: 5px;
  108. color: #444444;
  109. text-align: right;
  110. border: 3px solid #006cc2;
  111. background: #ffffff;
  112. z-index: 100;
  113. }
  114. .tgut:hover .m{
  115. display: block;
  116. }
  117. .tgut .in{
  118. width: 95px;
  119. }
  120. .tgut .but{
  121. color: #ffffff;
  122. border: 0;
  123. background: #006cc2;
  124. }
  125. .tgut .tag{
  126. margin: 0 0 10px;
  127. }
  128. .tgut .colors{
  129. margin: 0 0 10px;
  130. }
  131. .tgut .clor{
  132. margin: 0 0 10px;
  133. }
  134. .tgut .remv{
  135. margin: 0 0 10px;
  136. }
  137. .tgut .colors .c{
  138. float: right;
  139. width: 32px;
  140. height: 32px;
  141. margin: 0;
  142. }
  143. .tgut .colors .f{
  144. margin-right: 0;
  145. }
  146. .tgut .colors .c1{
  147. background: #641e16;
  148. }
  149. .tgut .colors .c2{
  150. background: #4a235a;
  151. }
  152. .tgut .colors .c3{
  153. background: #0b5345;
  154. }
  155. .tgut .colors .c4{
  156. background: #7d6608;
  157. }
  158. .tgut .colors .c5{
  159. background: #424949 ;
  160. }
  161. .tgut .colors .c6{
  162. background: #e74c3c;
  163. }
  164. .tgut .colors .c7{
  165. background: #f7dc6f;
  166. }
  167. .tgut .colors .c8{
  168. background: #85929e;
  169. }
  170. .tgut .colors .c9{
  171. background: #17a589 ;
  172. }
  173. .tgut .colors .c10{
  174. background: #f0b27a;
  175. }
  176. .tgut .colors .c11{
  177. background: #000000;
  178. }
  179. .tgut .colors .c12{
  180. background: #00ff00;
  181. }
  182. .tgut-tag{
  183. position: absolute;
  184. width: 130px;
  185. margin: 8px 0;
  186. color: #ffffff;
  187. text-align: center;
  188. line-height: 24px;
  189. border: 0;
  190. background: #006cc2;
  191. z-index: 50;
  192. }
  193. .tgut-page-cover{
  194. display: none;
  195. position:absolute;
  196. top: 0;
  197. left: 0;
  198. -moz-opacity: 0.6;
  199. opacity: 0.6;
  200. background-color: #000000;
  201. z-index: 200;
  202. }
  203. .tgut-popup{
  204. position: absolute;
  205. display: none;
  206. left: 50%;
  207. top: 10%;
  208. width: 60%;
  209. background: #ffffff;
  210. border: 5px solid #006cc2;
  211. z-index: 250;
  212. }
  213. .tgut-popup .f-l{
  214. float: left;
  215. }
  216. .tgut-popup .f-r{
  217. float: right;
  218. }
  219. .tgut-popup .tt{
  220. padding: 0 10px;
  221. line-height: 28px;
  222. color: #ffffff;
  223. background: #006cc2;
  224. }
  225. .tgut-popup .cls{
  226. }
  227. .tgut-popup .cls a{
  228. display: block;
  229. width: 24px;
  230. float: right;
  231. font-size: 120%;
  232. color: #fff;
  233. line-height: 24px;
  234. cursor: pointer;
  235. text-align: center;
  236. text-decoration: none;
  237. }
  238. .tgut-popup .cls a:hover{
  239. color: #0e5685;
  240. background: #fff;
  241. }
  242. .tgut-popup .ct{
  243. clear: both;
  244. __padding: 5px;
  245. text-align: left;
  246. }
  247. .tgut-posts{
  248. padding: 10px;
  249. }
  250. .tgut-posts .post{
  251. clear: both;
  252. margin: 10px 0 20px 0;
  253. padding: 10px;
  254. background: #f0f0f0;
  255. border-bottom: 2px solid #006cc2;
  256. overflow: hidden;
  257. }
  258. .tgut-posts .pid{
  259. float: right;
  260. margin: 0 20px 0 0;
  261. font-weight: bold;
  262. text-decoration: underline;
  263. }
  264. .tgut-posts .time{
  265. float: left;
  266. font-weight: bold;
  267. }
  268. .tgut-posts .del{
  269. float: right;
  270. }
  271. .tgut-posts .del button{
  272. color: #ffffff;
  273. border: 0;
  274. background: #006cc2;
  275. }
  276. .tgut-posts .ct{
  277. clear: both;
  278. margin: 10px 0;
  279. }
  280. .tgut-but{
  281. display: inline-block;
  282. margin: 4px 20px;
  283. padding: 0 10px;
  284. color: #ffffff;
  285. line-height: 25px;
  286. background: #006cc2;
  287. cursor: pointer;
  288. }
  289. .tgut-sett{
  290. padding: 10px;
  291. }
  292. .tgut-sett .but{
  293. color: #ffffff;
  294. border: 0;
  295. background: #006cc2;
  296. }
  297. .tgut-sett .b{
  298. text-align: right;
  299. }
  300. .tgut-sett .t{
  301. margin: 20px 0;
  302. }
  303. .tgut-sett .t .txa{
  304. width: 99%;
  305. height: 200px;
  306. }
  307. `
  308. );
  309.  
  310. $( 'body' ).append( HTML_MSG );
  311. $( 'body' ).append( HTML_POPUP );
  312.  
  313.  
  314. function test( v ){
  315. return ( v && v !== 0 && v != "0" );
  316. }
  317. function trim( txt ){
  318. return ( txt ? txt.replace( /^\s+|\s+$/g, "" ) : "" );
  319. }
  320. function html( s ){
  321. if( typeof s == 'string' ){
  322. return s.replace(/&/g, "&amp;")
  323. .replace(/</g, "&lt;")
  324. .replace(/>/g, "&gt;")
  325. .replace(/"/g, "&quot;")
  326. .replace(/'/g, "&#039;");
  327. }
  328. return '';
  329. }
  330. function count_obj( o, true_only ){
  331. var c = 0;
  332. for( var i in o ){
  333. true_only ? ( test( o[i] ) && c++ ) : c++;
  334. }
  335. return c;
  336. }
  337. function tl( o ){
  338. console.log( o );
  339. }
  340.  
  341.  
  342. var tg = {
  343.  
  344. is_logged_in: 0,
  345. data_init: {
  346. version: 2,
  347. users: {},
  348. posts: {},
  349. },
  350. user_init: {
  351. uid: 0,
  352. name: '',
  353. tag: '',
  354. color: '',
  355. remove_post: 0,
  356. parent_uid: 0,
  357. related_uids: {},
  358. quotes: {}
  359. },
  360. data: {},
  361.  
  362. msg: function( m ){
  363. $( '#tgut_msg' ).html( m ).stop( true, true ).show( 1, function(){ $( '#tgut_msg' ).animate( {"null":1}, 1000 ).fadeOut( 200 ); } );
  364. },
  365.  
  366. load_data: function(){
  367. var data = tg.data_init;
  368. var tmp = GM_getValue( DATA_FILE, "" );
  369.  
  370. try{
  371. data = JSON.parse( tmp );
  372. }catch( e ){
  373.  
  374. }
  375. if( test( data.version ) ){
  376. tg.data = data;
  377. }
  378. },
  379. save_data: function(){
  380. GM_setValue( DATA_FILE, JSON.stringify( tg.data ) );
  381. },
  382. clean_data: function(){
  383. tg.data = tg.data_init;
  384. tg.save_data();
  385. },
  386. update_data: function(){
  387. if( tg.data.version < 2 ){
  388. tg.data.posts = {};
  389. tg.data.version = 2;
  390. tg.save_data();
  391. }
  392. },
  393.  
  394. init: function(){
  395. // check if logged in
  396. var l = $( '#um' );
  397. if( l.length > 0 ){
  398. tg.is_logged_in = 1;
  399. // read in stored settings
  400. tg.load_data();
  401. tg.update_data();
  402.  
  403. post.init();
  404. sett.init();
  405. }else{
  406. // do nothing...
  407. }
  408.  
  409. pop.init();
  410. }
  411.  
  412. };
  413.  
  414. var pop = {
  415.  
  416. cover: function( on ){
  417. var c = $( '#tgut_page_cover' );
  418. var o = $( 'body' );
  419. if( on ){
  420. c.css( "width", o.width() ).css( "height", o.height() ).show();
  421. o.find( '.wrap:first' ).addClass( "tgut-blur" );
  422. }else{
  423. o.find( '.wrap:first' ).removeClass( "tgut-blur" );
  424. c.hide();
  425. }
  426.  
  427. },
  428.  
  429. show: function( t, c ){
  430. var o = $( '#tgut_popup' );
  431. var top = $(document).scrollTop() + ( o.height() > 500 ? 1 : 100 );
  432. $( '#tgut_popup_content' ).html( c );
  433. $( '#tgut_popup_title' ).html( ( t ) );
  434. o.css( "margin-left", - o.width() / 2 ).css( "top", top ).show();
  435. pop.cover( 1 );
  436. },
  437. close: function(){
  438. $( '#tgut_popup' ).hide();
  439. pop.cover();
  440. },
  441.  
  442. init: function(){
  443. $( '#tgut_popup_close' ).click( pop.close );
  444. }
  445. };
  446.  
  447.  
  448. var post = {
  449.  
  450. process_posts: function(){
  451. $( "#postlist" ).children( 'div' ).each(
  452. function(){
  453. var o = $( this );
  454. if( o.prop( 'id' ).indexOf( 'post_' ) == 0 ){
  455. var user = o.find( ".authi:first" ).css( "position", "relative" );
  456. var popup = o.find( ".userinfopanel" );
  457. o.find( '.pls' ).css( 'overflow', 'visible' );
  458. o.find( '.tgut' ).remove();
  459. user.parent().css( 'overflow', 'visible' )
  460.  
  461. var name = user.find( "a" ).html();
  462. var uid = post.get_uid( user );
  463. var pid = o.find( "table" ).first().prop( "id" ).replace( "pid", "" );
  464.  
  465. //tl( username + ":::" + uid + ":::" + pid );
  466. var tag = test( tg.data.users[uid] ) ? tg.data.users[uid] : tg.user_init;
  467. var h = HTML_USERNAME;
  468. h = h.replace( /PID/g, pid )
  469. .replace( /UID/g, uid )
  470. .replace( /TAG/g, html( tag.tag ) )
  471. .replace( /COLOR/g, html( tag.color ) )
  472. .replace( /REMOVE_POST/g, ( test( tag.remove_post ) ? 'checked' : '' ) );
  473. var j = new $( h );
  474. j.find( ".but-save-tag" ).click( post.save );
  475. j.find( ".but-save-post" ).click( post.save_post );
  476. j.find( ".but-view-posts" ).click( post.view_posts );
  477. j.find( ".c" ).click( post.color_click );
  478. user.append( j );
  479.  
  480. if( tag.uid == uid ){
  481. user.parent().find( '.tgut-tag' ).remove();
  482. if( test( tag.tag ) ){
  483. user.after( HTML_TAG.replace( /TAG/g, html( tag.tag ) ) );
  484. }
  485. user.closest( 'table' ).find( 'td' ).css( 'color', '' );
  486. if( test( tag.color ) ){
  487. user.closest( 'table' ).find( 'td' ).css( 'color', tag.color );
  488. }
  489. var s = o.find( 'favatar:first' );
  490. if( test( tag.remove_post ) ){
  491. //s.children("div:gt(0), p, dl, ul").css( 'display', 'none' );
  492. o.find( '.pct' ).css( 'display', 'none' ).after( '<div class="tgut-mesg">用户帖子和签名被屏蔽</div>' );
  493. o.find( '.sign' ).css( 'display', 'none' );
  494. }else{
  495. //s.children("div:gt(0), p, dl, ul").css( 'display', 'block' );
  496. o.find( '.pct' ).css( 'display', 'block' );
  497. o.find( '.sign' ).css( 'display', 'none' );
  498. o.find( '.tgut-mesg' ).remove();
  499. }
  500. }
  501. }
  502. }
  503. );
  504. },
  505. get_uid: function( d ){
  506. var h = d.find( 'a' ).prop( 'href' );
  507. var s = h.substring( h.lastIndexOf( "-" ) + 1, h.lastIndexOf( '.html' ) );
  508. return trim( s );
  509. },
  510. get_name: function( pid ){
  511. var name = $( '#pid' + pid ).find( 'cite:first' ).find( "a" ).html();
  512. return trim( name );
  513. },
  514. color_click: function( e ){
  515. var o = $( this );
  516. o.closest( ".tgut" ).find( "[name='color']" ).val( o.css( "background-color" ) );
  517.  
  518. },
  519. save: function( e ){
  520. var o = $( this ).closest( ".tgut" );
  521. var uid = o.data( "uid" );
  522. var pid = o.data( "pid" );
  523. var tag = o.find( "[name='tag']" ).val();
  524. var color = o.find( "[name='color']" ).val();
  525. var remove_post = o.find( "[name='remove_post']" ).is( ':checked' );
  526. if( !test( uid ) ){
  527. return;
  528. }
  529. if( !test( tg.data.users[uid] ) ){
  530. tg.data.users[uid] = tg.user_init;
  531. }
  532. tg.data.users[uid].uid = uid;
  533. tg.data.users[uid].tag = tag;
  534. tg.data.users[uid].name = post.get_name( pid );
  535. tg.data.users[uid].color = color;
  536. tg.data.users[uid].remove_post = remove_post ? 1 : 0;
  537. tg.save_data();
  538. tg.msg( "已保存用户标签" );
  539. post.process_posts();
  540. },
  541. save_post: function( e ){
  542. var o = $( this );
  543. var pid = o.data( 'pid' );
  544. var uid = o.data( 'uid' );
  545. var content = trim( $( '#postmessage_' + pid ).html() );
  546. var time_str = trim( $( '#authorposton' + pid ).text() ); // well well well....
  547.  
  548. if( !test( tg.data.posts[uid] ) ){
  549. tg.data.posts[uid] = {};
  550. }
  551. tg.data.posts[uid][pid] = {
  552. 'uid': uid,
  553. 'pid': pid,
  554. 'name': post.get_name( pid ),
  555. 'time': time_str,
  556. 'post': content
  557. };
  558.  
  559. tg.save_data();
  560. tg.msg( "帖子保存了" );
  561.  
  562. },
  563. del_post: function( e ){
  564. var o = $( this );
  565. var pid = o.data( 'pid' );
  566. var uid = o.data( 'uid' );
  567.  
  568. if( test( tg.data.posts[uid] ) && test( tg.data.posts[uid][pid] ) ){
  569. delete( tg.data.posts[uid][pid] );
  570. tg.save_data();
  571. tg.msg( "帖子删除了" );
  572. }
  573.  
  574. $( '#tgut_post_' + pid ).remove();
  575. if( !count_obj( tg.data.posts[uid] ) ){
  576. pop.close();
  577. }
  578.  
  579. },
  580. view_posts: function( e ){
  581. var o = $( this );
  582. var pid = o.data( 'pid' );
  583. var uid = o.data( 'uid' );
  584.  
  585. if( !test( tg.data.posts[uid] ) || !count_obj( tg.data.posts[uid] ) ){
  586. tg.msg( '没有针对该用户保存的帖子' );
  587. return;
  588. }
  589.  
  590. var name = '';
  591. var h = '<div class="tgut-posts">';
  592. for( var i in tg.data.posts[uid] ){
  593. var p = tg.data.posts[uid][i];
  594. name = p.name;
  595. h += '<div class="post" id="tgut_post_' +p.pid+ '"><div class="time">' +p.time+ '</div>' +
  596. '<div class="del"><button class="but" name="dummy" value="Del" data-pid="' +p.pid+ '" data-uid="' +p.uid+ '">删除</button></div>' +
  597. '<div class="pid"><a href="' +POST_URL+p.pid+ '" target="_blank">Post ID: ' +p.pid+ '</a></div>' +
  598. '<div class="ct">' +p.post+ '</div></div>';
  599. }
  600. h += '</div>';
  601. var j = new $( h );
  602. j.find( '.but' ).click( post.del_post );
  603. pop.show( name, j );
  604. },
  605.  
  606. init: function(){
  607. post.process_posts();
  608. }
  609.  
  610. };
  611.  
  612.  
  613. var sett = {
  614.  
  615. clean: function(){
  616. if( confirm( "确定删除所有以保存的用户标签以及帖子吗?" ) ){
  617. tg.clean_data();
  618. tg.save_data();
  619. tg.init();
  620. tg.msg( "数据已清除" );
  621. }
  622. },
  623. export: function(){
  624. var str = JSON.stringify( tg.data );
  625. $( '#tgut_data_text' ).val( str );
  626. tg.msg( "数据已显示在输入框中" );
  627. },
  628. import: function(){
  629. var data = {};
  630. var str = trim( $( '#tgut_data_text' ).val() );
  631. try{
  632. data = JSON.parse( str );
  633. }catch( e ){
  634. tg.msg( "数据不是有效的JSON字串" );
  635. return;
  636. }
  637. if( test( data.version ) ){
  638. tg.data = data;
  639. tg.update_data();
  640. tg.save_data();
  641. tg.msg( "成功导入数据" );
  642. tg.init();
  643. }else{
  644. tg.msg( "无法识别数据版本" );
  645. }
  646. },
  647. show: function(){
  648. var j = new $( HTML_SETTINGS );
  649. j.find( '.but-clean' ).click( sett.clean );
  650. j.find( '.but-export' ).click( sett.export );
  651. j.find( '.but-import' ).click( sett.import );
  652. pop.show( 'S1UT设置', j );
  653. },
  654.  
  655. init: function(){
  656. // find the user bar beside the log
  657. var o = $( '#nv' ).find( 'ul' );
  658. if( !o.find( '.tgut-but' ).length ){
  659. var j = new $( '<div class="tgut-but">S1UT</div>' );
  660. j.click( sett.show );
  661. o.parent().append( j );
  662. }
  663. }
  664. };
  665.  
  666.  
  667. tg.init();
  668.  
  669. })();