search broadcast for douban

search user braodcast

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         search broadcast for douban
// @namespace    harryhare.github.io
// @version      0.2.3
// @description  search user braodcast
// @author       harryhare
// @license      GPL 3.0
// @icon         https://raw.githubusercontent.com/harryhare/userscript/master/index.png
// @match        https://www.douban.com/people/*/statuses**
// @match        https://www.douban.com
// @match        https://www.douban.com/?p=*
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

const gm_key="douban_user_status";
const interval=2000;

var stop_signal=false;

var search_text;
var search_page;
var max_page;
var user_name;
var old_data;
var cached_status;
var cached_ids_set;
var latest_cached_id="";
var latest_cached_time="";

var result_container;
var status_container;
var search_button;
var stop_button;


var page=1;
var statuses=[];

function getContent(response){
	var target_string=search_text.value;
	var target_exp=new RegExp(target_string,"i");
	var parser=new window.DOMParser();
	var xmlDoc=parser.parseFromString(response,"text/html");
	//xmlDoc.getElementsByTagName('textarea')[0].innerHTML;
	var statuse_nodes=xmlDoc.querySelectorAll("div.stream-items div.new-status.status-wrapper");
	user_name = get_user_id();
	//console.log(statuses);
	for (var i=0;i<statuse_nodes.length;i++){
		var status= statuse_nodes[i];
		var create_time=status.querySelector("div.status-item div.mod div.bd div.actions span.created_at");
		var status_id=status.getAttribute('data-sid');
		//console.log("new status id: ",status_id);
		if(cached_ids_set.has(status_id)){
			//search in cached data
			cached_status=GM_getValue(gm_key)[user_name];
			for(let data of cached_status){
				var status=parser.parseFromString(data,"text/html").body.firstChild;
				var text=status.innerHTML;
				if(text.search(target_exp)!=-1){
					result_container.append(status);
				}
			}

			//merge
			console.log("new statuses: ");
			console.log(statuses.length);
			console.log("cached status: ");
			console.log(cached_status.length);
			statuses.push(...cached_status)

			console.log("merged status: ");
			console.log(statuses.length);
			return true;
		}
		//change time until now to post time
		if(create_time){
			var create_time_a=create_time.querySelector("a");
			if(create_time_a){
				create_time_a.innerHTML=create_time.getAttribute('title');
				statuses.push(status.outerHTML);
			}
		}

		var text=status.innerHTML;
		if(text.search(target_exp)!=-1){
			result_container.append(status);
		}
	}
	return statuse_nodes.length==0;
}


function visit(){
	var xhr=new XMLHttpRequest();
	var url=get_base_url()+"?p="+page;
	console.log('visit',url);
	status_container.innerHTML="正在搜索第"+page+"页...";
	xhr.open("GET",url,true);
	xhr.onreadystatechange = function (){
		if(xhr.readyState != 4 || xhr.status != 200 ){
			return;
		}
		console.log("recv:",url);
		//console.warn(xhr.responseText);
		let reach_end=getContent(xhr.responseText);
		if(page<max_page && reach_end==false && stop_signal==false){
			page++;
			var interval_id = window.setInterval(()=>{
				window.clearInterval(interval_id);
				visit();
				},interval);
		}else{
			finish();
		}
	};
	xhr.send();
}

var mode=""

function finish(){
	//save
	user_name=get_user_id();
	old_data[user_name]=statuses;
	GM_setValue(gm_key,old_data);


	//show finish
	console.log("done");
	search_button.disabled=false;
	stop_button.disabled=true;
	status_container.innerHTML="搜索完成";
}


function on_search(){
	console.log("do search");
	console.log("search text: ",search_text.value);
	console.log("max page: ",search_page.value);
	console.log("target user name: ",user_name);
	old_data=GM_getValue(gm_key);
	//console.log(old_data);
	if(!old_data){
		old_data=new Map();
	}

	//find the latest status id in old_data
	cached_status=[];
	cached_ids_set=new Set();
	if(old_data[user_name] && old_data[user_name].length>0){
		cached_status=old_data[user_name];
		var parser=new window.DOMParser();
		//var node=parser.parseFromString(old_data[user_name][0],"text/html").body.firstChild;
		//latest_cached_id=node.getAttribute('data-sid');
		//var create_time_node=node.querySelector("div.status-item div.mod div.bd div.actions span.created_at");
		//latest_cached_time=node.getAttribute('title');
		//console.log("last cached status id: ",latest_cached_id);
		for(let data of cached_status){
			var node=parser.parseFromString(data,"text/html").body.firstChild;
			var id=node.getAttribute('data-sid');
			cached_ids_set.add(id);
		}
	}

	//limit cache pages
	max_page=parseInt(search_page.value);
	if(!max_page||max_page<=1){
		max_page=20;
	}

	//disable search button and show progress
	result_container.innerHTML="";
	search_button.disabled=true;
	stop_button.disabled=false;
	stop_signal=false;

	//start visit
	page=1;
	statuses=[];
	visit();
}


function on_clean(){
	console.log("clean cache data");
	GM_setValue(gm_key,{});
}


function on_stop(){
	stop_signal=true;
}


function test(){
	console.log(search_text.value);
	console.log(search_page.value);
	console.log(user_name);
}

function get_base_url(){
	var reg=/https?:\/\/www.douban.com\/people\/([^\/]+)\/statuses.*/g;
	var result=reg.exec(window.location);
	if(result && result.length==2){
		return "/people/"+user_name+"/statuses";
	}
	var reg2=/https?:\/\/www.douban.com/g;
	var result2=reg.exec(window.location);
	if(result && result.length==1){
		return "/";
	}
	return "";
}

function get_user_id(){
	var reg=/https?:\/\/www.douban.com\/people\/([^\/]+)\/statuses.*/g;
	var result=reg.exec(window.location);
	if(result && result.length==2){
		return result[1];
	}
	var reg2=/https?:\/\/www.douban.com.*/g;
	var result2=reg2.exec(window.location);
	if(result2 && result2.length==1){
		return "$$self_feed$$";
	}
	return "";
}

(function() {
	'use strict';

	user_name=get_user_id();
	if(user_name===""){
		console.warn("error url");
		return;
	}

	var p_node=document.querySelector("body div#wrapper div#content div.clearfix div.aside");

	var container=document.createElement('div');
	container.style='background-color:#eeeeee;display: -webkit-flex; display: flex; flex-direction: column;';
	p_node.append(container);

	var title=document.createElement('div');
	title.innerHTML="搜索广播";
	container.append(title);

	//inputs
	var search_container=document.createElement('div');
	search_container.style='display: -webkit-flex; display: flex; flex-direction: row;  justify-content: space-between ;';
	container.append(search_container);

	var text1=document.createElement('div');
	text1.innerHTML="关键字:";
	search_container.append(text1);

	search_text=document.createElement('input');
	search_text.style="width:220px;flex:0 1 auto;";
	search_container.append(search_text);

	var page_container=document.createElement('div');
	page_container.style='display: -webkit-flex; display: flex; flex-direction: row; justify-content: space-between ;';
	container.append(page_container);

	var text2=document.createElement('div');
	text2.innerHTML="最大页数:";
	page_container.append(text2);

	search_page=document.createElement('input');
	search_page.style="width:220px;flex:0 1 auto;";
	page_container.append(search_page);
	search_page.value='10';

	//buttons
	var button_container=document.createElement('div');
	button_container.style='display: -webkit-flex; display: flex; flex-direction: row; justify-content: space-around ;';
	container.append(button_container);

	search_button=document.createElement('button');
	search_button.innerHTML="search";
	search_button.onclick=on_search;
	search_button.id="search";
	button_container.append(search_button);

	stop_button=document.createElement('button');
	stop_button.innerHTML="stop searching";
	stop_button.onclick=on_stop;
	stop_button.id="stop";
	stop_button.disabled=true;
	button_container.append(stop_button);

	var clean_button=document.createElement('button');
	clean_button.innerHTML="clean cache";
	clean_button.onclick=on_clean;
	clean_button.id="clean";
	button_container.append(clean_button);

	//var test_button=document.createElement('button');
	//test_button.innerHTML="test";
	//test_button.onclick=test;
	//test_button.id="test";
	//button_container.append(test_button);

	//results
	status_container=document.createElement('div');
	container.append(status_container);
	result_container=document.createElement('div');
	container.append(result_container);
})();