182 lines
5.6 KiB
TypeScript
182 lines
5.6 KiB
TypeScript
import { OTISSettingsPage } from "./settings";
|
|
import { GrapeSearch } from "./GrapeSearch";
|
|
import css from "./style.css";
|
|
|
|
|
|
|
|
import { DanboIcon } from "./Icons";
|
|
import { DANBOORU_API, danbo_artist, danbo_artist_search } from "./api";
|
|
import { createSignal, Show, For } from "solid-js";
|
|
import { click_out_directive, delay } from "./helper";
|
|
import { GM_addStyle } from 'vite-plugin-monkey/dist/client';
|
|
const clickOutside = click_out_directive
|
|
|
|
type UserSearchParams = {
|
|
username: string,
|
|
user_id: string,
|
|
is_tweet_page: bool
|
|
}
|
|
|
|
function ArtistSearch({username,user_id, is_tweet_page}:UserSearchParams) {
|
|
//const DanboIcon = ({onClick}:any) => <img onClick={onClick} src={danbo_icon} class={"otis-danbo-icon"} />
|
|
|
|
let danboIcon;
|
|
const [Artist,setArtist] = createSignal<danbo_artist>();
|
|
const [ShowUrls, setShowUrls] = createSignal<boolean>(false);
|
|
|
|
const ArtistSearchClicked = async (e:MouseEvent) => {
|
|
|
|
const ico = danboIcon as HTMLImageElement;
|
|
ico.classList.add('otis-icon-loading');
|
|
ico.classList.remove('otis-icon-noresult');
|
|
|
|
const res = await danbo_artist_search(username)
|
|
console.debug(res || "not found")
|
|
ico.classList.remove('otis-icon-loading');
|
|
|
|
if ( !res ) {
|
|
ico.classList.add('otis-icon-noresult');
|
|
ico.title = "No artist tag found on Danbooru"
|
|
return console.debug("artist: none")
|
|
}
|
|
|
|
setArtist(res);
|
|
|
|
if ( res.urls.length >= 1 ) setShowUrls(true)
|
|
|
|
}
|
|
return (
|
|
<span class={"danbo-artist-name tweet-button"} onClick={ArtistSearchClicked} classList={{"danbo-artist-name-tweetpage": is_tweet_page}}>
|
|
<DanboIcon
|
|
ref={danboIcon}
|
|
title="Perform manual artist search on Danbooru"
|
|
/>
|
|
<Show
|
|
when={Artist()}
|
|
fallback={ is_tweet_page ? "Artist Search": ""} >
|
|
<a
|
|
onmouseover={() => setShowUrls(true)}
|
|
href={ !(Artist().is_banned)
|
|
? `${DANBOORU_API}/posts?tags=${Artist().name}`
|
|
: `${DANBOORU_API}/artists/${Artist().id}`}
|
|
classList={{"danbo-artist-banned": Artist().is_banned}}
|
|
target="_blank" >
|
|
{Artist().name}
|
|
</a>
|
|
<div
|
|
class={"dropdown-menu"}
|
|
hidden={!ShowUrls()}
|
|
onmouseleave={() => setShowUrls(false)}
|
|
use:clickOutside={() => setShowUrls(false)}>
|
|
<For each={Artist().urls} >
|
|
{ ({url}) =>
|
|
<a href={url} target="_blank"> {url} </a>
|
|
}
|
|
</For>
|
|
</div>
|
|
</Show>
|
|
</span>
|
|
)
|
|
}
|
|
|
|
async function main() {
|
|
|
|
// check current page. Switch to Settings page instead
|
|
const settings_page = document.URL.endsWith("/old/settings");
|
|
if ( settings_page ) return OTISSettingsPage()
|
|
|
|
const callback : MutationCallback = (mutationList, observer) => {
|
|
for (const mutation of mutationList) {
|
|
if (mutation.type !== "childList") return;
|
|
|
|
mutation.addedNodes.forEach( (node) => {
|
|
|
|
const tweet = node as HTMLElement;
|
|
const media = tweet.getElementsByClassName('tweet-media').item(0);
|
|
if ( !media ) return;
|
|
|
|
const imgs = media.getElementsByTagName('img');
|
|
if ( !imgs ) return;
|
|
|
|
const vids = media.getElementsByTagName('video');
|
|
console.debug(vids);
|
|
if ( vids.length ) return;
|
|
|
|
const twt_interact = tweet.getElementsByClassName('tweet-interact').item(0);
|
|
const twt_avatar = tweet.getElementsByClassName('tweet-avatar-link').item(0) as HTMLAnchorElement;
|
|
const twt_child_elipsis = twt_interact?.getElementsByClassName('tweet-interact-more').item(0);
|
|
|
|
const twt_time = tweet.getElementsByClassName('tweet-time').item(0);
|
|
const twt_body = tweet.getElementsByClassName('tweet-body-main').item(0);
|
|
|
|
|
|
const tweet_id = tweet.dataset.tweetId || "0"
|
|
const tweet_user = twt_avatar.href.split('/').pop() || "*"
|
|
|
|
//console.debug({tweet_id: tweet_id, media:imgs?.length || 0});
|
|
//console.debug({tweet_user:tweet_user});
|
|
|
|
let img_urls = []
|
|
for ( const img of imgs ) {
|
|
img_urls.push(img.src)
|
|
}
|
|
//console.debug({media:img_urls, id:tweet_id, user:tweet_user});
|
|
const grape = () => <GrapeSearch media_url={img_urls} id={tweet_id} username={tweet_user}/>;
|
|
const artist = () => <ArtistSearch username={tweet_user} user_id={tweet_id} is_tweet_page={Boolean(twt_body)}/>
|
|
|
|
if ( !twt_body ) twt_time?.after(artist());
|
|
else twt_body?.prepend(artist());
|
|
|
|
twt_child_elipsis?.before(...grape());
|
|
|
|
// TODO: Implement OTIS buttons
|
|
})
|
|
}
|
|
};
|
|
|
|
|
|
const tweet_observer = new MutationObserver(callback);
|
|
const timeline = document.getElementById('timeline');
|
|
if ( !timeline ) return;
|
|
const config: MutationObserverInit = {
|
|
subtree:false,
|
|
childList:true,
|
|
attributes:false
|
|
}
|
|
tweet_observer.observe(timeline, config);
|
|
|
|
}
|
|
|
|
|
|
const init:any = async (limit=0) => {
|
|
/* We need to do this hack because Old Twitter Extension
|
|
would just dump entire Twitter's page including userscripts
|
|
and replace it with OT's custom page instead of replacing
|
|
Twitter's Document Body page
|
|
*/
|
|
|
|
if ( limit >= 5 ) return console.error("OTIS: Old Twitter Extension not detected, userscript won't run")
|
|
const element = document.getElementById('center-cell');
|
|
if (element) {
|
|
console.debug("Old Twitter detected");
|
|
const w = GM_addStyle(css);
|
|
return main();
|
|
}
|
|
else {
|
|
console.debug("can't find it");
|
|
await delay(1000);
|
|
return init(limit += 1);
|
|
}
|
|
}
|
|
//
|
|
init()
|
|
|
|
// const element = document.getElementById('center-cell');
|
|
// if (element) {
|
|
// console.debug("Old Twitter Extension detected");
|
|
// main();
|
|
// }
|
|
// else {
|
|
// console.debug("can't find it");
|
|
// }
|