본문으로 이동

사용자:Hsl0/연구소/숫자야구 live/실시간.js

리버티게임, 모두가 만들어가는 자유로운 게임
imported>Hsl0님의 2020년 8월 17일 (월) 22:11 판

참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.

  • 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
  • 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
  • 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
const api = new mw.Api();

export class LiveClient extends EventTarget {
	constructor(title, options) {
		super();
		this.src = title;
		this.interval = null;
		this.loadParams = options && options.loadParams || {
			action: "query",
			curtimestamp: true,
			prop: "revisions",
			titles: this.src,
			formatversion: 2,
			rvprop: ['ids', 'timestamp', 'user', 'content'],
			rvlimit: "max",
			rvdir: "newer",
		};
		this.postParams = options && options.postParams || {
			action: "edit",
			curtimestamp: true,
			title: this.src,
			minor: true
		};
		this.now = {
			id: null,
			timestamp: null
		};
	}
	load(from, options = {}) {
		const params = {};
		switch(typeof from) {
			case 'string':
				params.rvcontinue = from;
				break;
			case 'object':
				if(from.timestamp) {
					if(from.id) params.rvcontinue = from.timestamp + '|' + from.id;
					else params.rvfrom = from.timestamp;
				} else if(from.id) params.rvfromid = from.id;
				break;
		}
		
		return api.get(Object.assign(params, this.loadParams, options.params), options.ajax).then(response => {
			if(response.error) {
				throw {
					type: 'api',
					error: response.error,
					response
				};
			} else {
				const revisions = response.query && response.query.pages[0].revisions;
				const result = {response, revisions};
				
				if(!options.silent) setTimeout(() => super.dispatchEvent(new CustomEvent('update', {
					detail: result
				})), 0);
				
				return result;
			}
		}, error => {
			throw {
				type: 'fetch',
				error,
				response: null
			};
		});
	}
	post(content) {
		return api.postWithEditToken(Object.assign({
			text: content
		}, this.postParams));
	}
	start(interval) {
		if(typeof interval !== 'number') throw new TypeError('정상적인 간격이 지정되지 않았습니다');
		
		this.interval = interval;
		const client = this;
		
		function load(options) {
			client.load(client.now, options).then(result => {
				if(client.interval !== null) {
					const response = result.response;
					const revisions = result.revisions;
					
					result.error = false;
					result.updated = Boolean(revisions);
					delete result.revisions;
					super.dispatchEvent(new CustomEvent('fetch', {
						detail: result
					}));
					
					if(revisions) {
						if(response.continue) {
							client.now = response.continue.rvcontinue;
							
							return load();
						} else {
							const last = revisions[revisions.length - 1];
							client.now = {
								id: last.revid,
								timestamp: last.timestamp
							};
							client.now.id++;
						}
					}
					
					setTimeout(load, client.interval, {
						params: {
							maxage: 0
						}
					});
				}
			}, error => {
				super.dispatchEvent(new CustomEvent('error', {
					detail: error
				}));
				
				if(error.type === 'api') super.dispatchEvent(new CustomEvent('fetch', {
					detail: {
						response: error.response,
						error: true,
						updated: false
					}
				}));
			});
		}
		load();
		
		return this;
	}
	stop() {
		this.interval = null;
		
		return this;
	}
	dispatchEvent() {
		throw new TypeError('이벤트를 임의로 발생시킬 수 없습니다');
	}
}