Last active
July 10, 2021 12:59
-
-
Save aymkx/b6e9d807d47294befdd7a72f480fb6bd to your computer and use it in GitHub Desktop.
TweetDeckのActivityカラムにフィルターをかけるUserScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
class Article { | |
readonly dom: HTMLElement; | |
readonly userId: string = ""; | |
readonly userName: string = ""; | |
readonly screenName: string = ""; | |
readonly tweetId?: string; | |
readonly tweetUrl?: string; | |
readonly timestamp?: Date; | |
readonly body?: string; | |
readonly activityType?: string; | |
readonly activityUserId?: string; | |
readonly activityUserName?: string; | |
readonly activityUserSN?: string; | |
constructor(ar: HTMLElement) { | |
this.dom = ar; | |
const acHeader = ar.querySelector("div.activity-header"); | |
const splited = ar.dataset["key"]?.split("_"); | |
if (splited !== undefined && splited.length > 1) { | |
this.activityType = splited[0]; | |
if (this.activityType == "gap") { | |
throw new Error("argument is not article"); | |
} | |
this.activityUserId = splited[1]; | |
if (this.activityType === "follow") { | |
this.userId = splited[2]; | |
} | |
} | |
for (const a of acHeader?.getElementsByTagName("a") || []) { | |
if (a.classList.contains("account-link")) { | |
const url = new URL(a.href); | |
this.activityUserSN = url.pathname.substring(1); | |
this.activityUserName = a.innerText; | |
} | |
} | |
if (ar.dataset["dragType"] === "tweet") { | |
this.tweetId = ar.dataset["tweetId"]; | |
const header = ar.querySelector("header"); | |
const time = header?.getElementsByTagName("time"); | |
if (time !== undefined && time.length > 0) { | |
this.timestamp = new Date(time[0].dateTime); | |
const a = time[0].querySelector("a"); | |
if (a !== null) { | |
this.tweetUrl = a.href; | |
} | |
} | |
for (const a of header?.getElementsByTagName("a") || []) { | |
if (a.classList.contains("account-link")) { | |
const url = new URL(a.href); | |
this.screenName = url.pathname.substring(1); | |
} | |
} | |
this.userName = | |
header?.querySelector<HTMLElement>("b.fullname")?.innerText || ""; | |
const body = ar.querySelector<HTMLElement>("div.tweet-body"); | |
this.body = body?.innerText.trim(); | |
const footer = ar.querySelector("footer"); | |
for (const li of footer?.querySelectorAll("li.tweet-action-item") || []) { | |
for (const a of li.getElementsByTagName("a")) { | |
this.userId = a.dataset["userId"] || ""; | |
} | |
} | |
} else { | |
const acSum = ar.querySelector<HTMLElement>("div.account-summary"); | |
for (const a of acSum?.getElementsByTagName("a") || []) { | |
if (a.classList.contains("account-link")) { | |
const url = new URL(a.href); | |
this.screenName = url.pathname.substring(1); | |
} | |
} | |
this.userName = | |
acSum?.querySelector<HTMLElement>("b.fullname")?.innerText || ""; | |
} | |
} | |
} | |
function isActivityColumn(c: Element): boolean { | |
if (c.className.includes("column")) { | |
for (const t of c.getElementsByClassName("column-title")) { | |
if ( | |
t instanceof HTMLElement && | |
t.innerText.toLowerCase().includes("activity") | |
) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
function getActivityColumn(): HTMLElement | undefined { | |
for (const s of document.getElementsByTagName("section")) { | |
if (isActivityColumn(s)) { | |
return s; | |
} | |
} | |
} | |
function isToBeHidden(article: Article): boolean { | |
const activity = "favorite"; | |
const sn = "<screen_name>"; | |
return article.activityType === activity && article.activityUserSN === sn; | |
} | |
async function filter(articleElement: HTMLElement) { | |
if (articleElement.dataset["key"]?.startsWith("gap_")) { | |
return; | |
} | |
const article = new Article(articleElement); | |
if (isToBeHidden(article) && article.dom.style.display !== "none") { | |
article.dom.style.display = "none"; | |
console.log(article); | |
} | |
if (article.activityType !== "favorite") { | |
console.log(article); | |
} | |
} | |
function nodeFilter(n: Node): void { | |
if (n instanceof HTMLElement) { | |
if (n.tagName.toLowerCase() === "article") { | |
filter(n); | |
} else { | |
for (const a of n.getElementsByTagName("article")) { | |
filter(a); | |
} | |
} | |
} | |
} | |
const config = { | |
childList: true, | |
attributes: true, | |
subtree: true, | |
}; | |
const mo = new MutationObserver((mutationList, observer) => { | |
for (const m of mutationList) { | |
switch (m.type) { | |
case "childList": | |
for (const n of m.addedNodes) { | |
if ( | |
n instanceof Element && | |
n.tagName.toLowerCase() === "section" && | |
isActivityColumn(n) | |
) { | |
observer.disconnect(); | |
observer.observe(n, config); | |
} | |
nodeFilter(n); | |
} | |
break; | |
case "attributes": | |
if (m.attributeName === "style") { | |
nodeFilter(m.target); | |
} | |
break; | |
} | |
} | |
}); | |
mo.observe(getActivityColumn() || document, config); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ฅ^•ﻌ•^ฅ