// ==UserScript==
// @name Call for Nano
// @namespace http://tampermonkey.net/
// @version 0.1.2
// @description 自动发送Nanoなの☆エボリューション应援歌词
// @author ADDD
// @include /https?:\/\/live\.bilibili\.com\/?\??.*/
// @include /https?:\/\/live\.bilibili\.com\/\d+\??.*/
// @include /https?:\/\/live\.bilibili\.com\/(blanc\/)?\d+\??.*/
// @require https://code.jquery.com/jquery-3.6.0.min.js
// @require https://cdn.bootcss.com/jqueryui/1.12.1/jquery-ui.min.js
// @require https://cdn.staticfile.org/axios/0.27.2/axios.min.js
// @grant none
// @license MIT
// @icon https://i0.hdslb.com/bfs/garb/d926ea632254c7dff67f7cbf59a0a9eaaf74bb1b.png
// ==/UserScript==
(function() {
// 歌曲来源 https://shiinanoha.com/archives/10936 - 菜の花字幕组
const AUDIO_SRC = "https://shiinanoha.com/wp-content/uploads/2022/07/Nano%E3%81%AA%E3%81%AE%E2%98%86%E3%82%A8%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.mp3";
// 打Call图片
const IMAGE_SRC = "data:image/png;base64,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";
// Nano用户Id
const NANO_UID = 623441612;
// Nano直播间Id
const NANO_ROOM_ID = 22347054;
// 弹幕间隔时间
const INTERVAL = 1000;
// 原曲歌词
const ORIGIN_LYRICS = [
{ time:"00:00.00", content:""},
{ time:"00:02.32", content:"Nanoなの☆はい!"},
{ time:"00:14.54", content:"ぐるぐる迷路 地図片手に"},
{ time:"00:20.67", content:"指差し確認して 準備OK"},
{ time:"00:26.25", content:"朝まで解いた宿題持って"},
{ time:"00:30.76", content:"今日もいってきます(いってきまーす)"},
{ time:"00:36.69", content:"天気予報土砂降り雨でも"},
{ time:"00:42.31", content:"傘なんていらない!いっせーのでJump!"},
{ time:"00:47.52", content:"背伸びしても届かないなら"},
{ time:"00:53.47", content:"お空目指して 羽ばたこう"},
{ time:"00:59.02", content:"謎々だらけ この地球を"},
{ time:"01:04.61", content:"ぐるっと一回り"},
{ time:"01:10.15", content:"小っちゃくても大きいハートで"},
{ time:"01:12.70", content:"あなたの一番になりたいから"},
{ time:"01:15.57", content:"私のプログレス ずっと見ていて"},
{ time:"01:18.96", content:"やっぱり君なの Nanoなの☆yeah!"},
{ time:"01:32.64", content:"大きめブラシふんわりチーク"},
{ time:"01:38.83", content:"赤いマニキュア フリルのスカート"},
{ time:"01:44.36", content:"鏡の私とウインク練習"},
{ time:"01:48.92", content:"上手にできるかな?"},
{ time:"01:54.84", content:"あれもこれも 過ぎてく時間に"},
{ time:"02:00.47", content:"待って待って追いかけてjump!"},
{ time:"02:05.64", content:"あなたの瞳に小さくても"},
{ time:"02:11.59", content:"私可愛く映っていますか?"},
{ time:"02:17.16", content:"昨日の涙拭ったら"},
{ time:"02:22.75", content:"明日を迎えに行くの"},
{ time:"02:28.32", content:"小っちゃくても大きいハートで"},
{ time:"02:30.92", content:"あなたの一番でいられるなら"},
{ time:"02:33.75", content:"楽しいことは10億倍 やっぱり君なの"},
{ time:"03:01.46", content:"こんなに小さな声でも"},
{ time:"03:07.43", content:"見つけてくれてありがとう"},
{ time:"03:12.94", content:"これからもずっとずっと"},
{ time:"03:18.54", content:"そばにいてくれますか?"},
{ time:"03:26.54", content:"背伸びしても届かないなら"},
{ time:"03:32.52", content:"お空目指して 羽ばたこう"},
{ time:"03:38.11", content:"謎々だらけ この地球を"},
{ time:"03:43.71", content:"ぐるっと一回り"},
{ time:"03:49.27", content:"小っちゃくても大きいハートで"},
{ time:"03:51.94", content:"あなたの一番になりたいから"},
{ time:"03:54.66", content:"私のプログレス ずっと見ていて"},
{ time:"03:58.04", content:"やっぱり君なの Nanoなの☆yeah!"},
{ time:"04:12.14", content:"Nanoなの☆"},
];
// 打call歌词
const CHEER_LYRICS = [
{ mode: [], time: "00:00.00", content: "" },
{ mode: [1], time: "00:03.18", content: "嗨!" },
{ mode: [2], time: "00:03.58", content: "wu oi!wu oi!wu oi!wu oi!" }, // ウーオイ!ウーオイ!ウーオイ!ウーオイ! // 过长
{ mode: [3], time: "00:06.36", content: "a~👏👏sha-ikuzo!" }, // あーーよっしゃいくぞー!
{ mode: [1, 2], time: "00:09.49", content: "tiger fire cyber fiber" }, // タイガー!ファイヤー!サイバー!ファイバー! // 过长
{ mode: [3], time: "00:12.25", content: "diver viber jia-jia-!" }, // ダイバー!バイバー!ジャージャー! // 过长
{ mode: [1, 2], time: "00:19.27", content: "nanoha-!" },
{ mode: [3], time: "00:23.13", content: "cho-zetu kawaii nanoha-!" }, // 问就是 「超絶可愛い なのはー!」 有b站屏蔽词 // 过长
{ mode: [1, 3], time: "00:30.41", content: "nanoha-!" },
{ mode: [2], time: "00:34.26", content: "cho-zetu kawaii nanoha-!" }, // 问就是 「超絶可愛い なのはー!」 有b站屏蔽词 // 过长
{ mode: [1, 3], time: "00:37.05", content: "na-noha! na-noha!" },
{ mode: [2], time: "00:39.85", content: "na-noha! na-noha!" }, // 频率过快
{ mode: [2, 3], time: "00:45.76", content: "yeah tiger faibo wiper" }, // タイガー!ファイボー!ワイパー! // 过长
{ mode: [1], time: "00:49.48", content: "Ah-fufu-!" },
{ mode: [2], time: "00:52.43", content: "👏👏 fuwafuwa!" },
{ mode: [1], time: "00:55.58", content: "嗨 se-no!" },
{ mode: [3], time: "00:56.57", content: "嗨~嗨!嗨嗨嗨嗨" },
{ mode: [2], time: "01:00.64", content: "Ah-fufu-!" },
{ mode: [1, 3], time: "01:03.46", content: "👏👏 fuwafuwa!" },
{ mode: [1, 2, 3], time: "01:10.56", content: "喔~嗨!喔~嗨!喔~嗨!喔~嗨!" },
{ mode: [1], time: "01:21.33", content: "嗨!" },
{ mode: [2], time: "01:21.75", content: "wu oi!wu oi!wu oi!wu oi!" }, // ウーオイ!ウーオイ!ウーオイ!ウーオイ! // 过长
{ mode: [3], time: "01:24.49", content: "a~👏👏sha-ikuzo!" },
{ mode: [2, 3], time: "01:27.64", content: "tora hi jinzou seni" }, // 问就是 「(se)ni 」是b站屏蔽词 // 虎(とら)、火(ひ)、人造(じんぞう)、繊维(せんい)
{ mode: [1], time: "01:30.42", content: "ama shindou kasse-n!" }, // 海女(あま)、振动(しんどう)、化繊飞除去(かせんとびじょきょ)
{ mode: [2, 3], time: "01:37.39", content: "nanoha-!" }, // なのはー!
{ mode: [1], time: "01:41.25", content: "cho-zetu kawaii nanoha-!" }, // 问就是 「超絶可愛い なのはー!」 有b站屏蔽词 // 过长
{ mode: [1, 3], time: "01:48.58", content: "nanoha-!" }, // なのはー!
{ mode: [2], time: "01:52.41", content: "cho-zetu kawaii nanoha-!" }, // 问就是 「超絶可愛い なのはー!」 有b站屏蔽词 // 过长
{ mode: [1, 2], time: "02:03.92", content: "yeah tiger faibo wiper" }, // 过长
{ mode: [3], time: "02:07.61", content: "Ah-fufu-!" },
{ mode: [1, 2], time: "02:10.56", content: "👏👏 fuwafuwa!" },
{ mode: [3], time: "02:13.71", content: "嗨 se-no!" },
{ mode: [1, 2], time: "02:14.75", content: "嗨~嗨!嗨嗨嗨嗨" },
{ mode: [3], time: "02:18.76", content: "Ah-fufu-!" },
{ mode: [1, 2], time: "02:21.74", content: "👏👏 fuwafuwa!" },
{ mode: [1, 2, 3], time: "02:28.71", content: "喔~嗨!喔~嗨!喔~嗨!喔~嗨!" },
{ mode: [2, 3], time: "02:39.87", content: "iitai kotoga arundayo" }, // 言いたいことがあるんだよ! // 过长
{ mode: [1], time: "02:42.60", content: "yappari nanohawa kawaiiyo" }, // やっぱりなのははかわいいよ! // 过长
{ mode: [3], time: "02:45.46", content: "suki suki daisuki yappa suki" }, // すきすき大好き!やっぱ好き! // 过长
{ mode: [1], time: "02:48.22", content: "yatto mituketa ohimesama" }, // 问就是 「やっと見つけたお姫様!」 有b站屏蔽词 // 过长
{ mode: [2], time: "02:50.96", content: "orega umarete kitariyuu" }, // 俺が生まれてきた理由! // 过长
{ mode: [3], time: "02:53.80", content: "sorewa nanohani deautame" }, // 问就是 「それはなのはに出会うため!」 有b站屏蔽词 // 过长
{ mode: [1, 2], time: "02:56.56", content: "oreto Isshoni jinsei ayumou" }, // 问就是 jin(se)i 是b站屏蔽词 俺と一緒に人生歩もう // 过长
{ mode: [3], time: "02:59.32", content: "sekaide itiban aishiteru-!" }, // 世界で一番愛してる! // 过长
{ mode: [2, 3], time: "03:24.53", content: "👏👏👏👏" },
{ mode: [1], time: "03:27.31", content: "👏~👏~👏~👏~" },
{ mode: [3], time: "03:34.57", content: "嗨 se-no!" },
{ mode: [1], time: "03:35.63", content: "嗨~嗨!嗨嗨嗨嗨" },
{ mode: [2], time: "03:39.69", content: "Ah-fufu-!" },
{ mode: [1, 3], time: "03:42.72", content: "👏👏 fuwafuwa!" },
{ mode: [1, 3], time: "03:49.64", content: "喔~嗨!喔~嗨!喔~嗨!喔~嗨!" },
{ mode: [2], time: "03:50.64", content: "👏👏👏👏*4" },
{ mode: [3], time: "04:00.42", content: "嗨!" },
{ mode: [1], time: "04:00.80", content: "wu oi!wu oi!wu oi!wu oi!" }, // ウーオイ!ウーオイ!ウーオイ!ウーオイ! // 过长
{ mode: [2], time: "04:03.60", content: "wu oi!wu oi!wu oi!wu oi!" }, // ウーオイ!ウーオイ!ウーオイ!ウーオイ! // 过长
{ mode: [1, 3], time: "04:06.36", content: "wu oi!wu oi!wu oi!wu oi!" }, // ウーオイ!ウーオイ!ウーオイ!ウーオイ! // 过长
{ mode: [1, 2, 3], time: "04:13.42", content: "foo-!" },
];
// 布局设置
const setup = () => {
$(".player-section").append(
`<style>
#call-container {
position: absolute;
left: 10%;
top: 10%;
color: white;
font-size: 1.2rem;
font-family: "微软雅黑";
}
#call-img-container {
position: absolute;
}
#action-container {
position: absolute;
width: 440px;
background-color: #333;
margin: auto;
opacity: 0.9;
}
#lyric-content {
width: 440px;
height: 480px;
overflow: hidden;
position: relative;
opacity: 0.9;
}
#action-bar {
display: flex;
flex-direction: row;
margin: 14px;
align-items: center;
}
#button-group {
display: flex;
height: 54px;
flex-direction: column;
align-items: flex-start;
justify-content: space-around;
}
#button-group button {
display: flex;
color: black;
font-size: 0.8rem;
}
#audio-container {
display: flex;
}
#audio-container audio {
display: flex;
height: 30px;
}
#call-img {
width: 50px;
height: 50px;
border-radius: 10px;
}
#lyric-content ul {
width: 100%;
position: absolute;
top: 0;
left: 0;
list-style: none;
}
.original {
height: 30px;
line-height: 30px;
text-align: left;
padding-left: 30px;
}
.original.active {
color: #2ecc71;
font-weight: bold;
font-size: 20px;
}
.cheerful {
height: 30px;
line-height: 30px;
text-align: right;
padding-right: 30px;
}
.cheerful.active {
color: #f35858;
font-weight: bold;
font-size: 20px;
}
</style>
<div id="call-container">
<div id="call-img-container">
<img id="call-img" />
</div>
<div id="action-container">
<div id="lyric-content"></div>
<div id="action-bar">
<div id="button-group">
<button id="mode">模式1</button>
<button id="call">点我打Call</button>
</div>
<div id="audio-container">
<audio controls></audio>
</div>
</div>
</div>
</div>`);
};
// 初始化插件
const initCheer = () => {
const $ul = $("<ul></ul>");
const parsedOriginLyrics = [];
const parsedCheerLyrics = [];
let isCalling = false;
let mode = 0;
const audio = $("#audio-container audio")[0];
// 初始化音频
const initAudio = (audioSrc) => {
audio.src = audioSrc;
audio.muted = true;
let lastCheerLineNo = 0;
let timer = null;
// 当快进或者倒退时 找到该时点所属行
const getLineNo = (currentTime, lyrics) => {
const length = lyrics.length - 1;
for (let i = 0; i < length; ++i) {
if (
currentTime >= parseFloat(lyrics[i].time) &&
currentTime < parseFloat(lyrics[i + 1].time)
) {
return i;
}
}
return length;
};
// 节流
const throttle = (func) => {
timer = setTimeout(() => {
func;
timer = null;
}, INTERVAL);
};
// 歌曲播放时渲染
audio.addEventListener("timeupdate", () => {
const MIN_SCROLL_LINE = 6; // 第6行起开始滚动歌词
const LINE_HEIGHT = -30; // 每次滚动的距离
if ($("li").eq(0).hasClass("active")) {
$("ul").css("top", "0");
}
// 获取原曲该时点播放行
const originLineNo = getLineNo(audio.currentTime, parsedOriginLyrics);
// 获取打call时该时点播放行
const cheerLineNo = getLineNo(audio.currentTime, parsedCheerLyrics);
// 输出模式判断
// if (isCalling && timer === null && cheerLineNo !== lastCheerLineNo && parsedCheerLyrics[cheerLineNo].mode.includes(mode + 1)) {
if (isCalling && timer === null && cheerLineNo !== lastCheerLineNo) {
// 播放其他行歌词
lastCheerLineNo = cheerLineNo;
// 发送弹幕
throttle(sendMessage(parsedCheerLyrics[cheerLineNo].content));
}
// 歌词高亮
$("li.original")
.eq(originLineNo)
.addClass("active")
.siblings(".original")
.removeClass("active");
$("li.cheerful")
.eq(cheerLineNo)
.addClass("active")
.siblings(".cheerful")
.removeClass("active");
// 滚动播放
if (originLineNo > MIN_SCROLL_LINE || cheerLineNo > MIN_SCROLL_LINE) {
$ul
.stop(true, true)
.animate({ top: (originLineNo + cheerLineNo - MIN_SCROLL_LINE) * LINE_HEIGHT });
}
});
};
// 初始化歌词内容
const initLyricContent = (originalLyrics, cheerLyrics) => {
const lyricContent = $("#lyric-content");
// 时间处理
const parseTimeFromLyric = (lyric) => {
const splittedTime = lyric.time.split(":");
const minute = splittedTime[0];
const second = splittedTime[1];
return (parseInt(minute) * 60 + parseFloat(second)).toFixed(4) - 0;
};
// 文本处理
const parseContentFromLyric = (lyric) => {
return lyric.content;
};
originalLyrics.forEach((lyric) => {
parsedOriginLyrics.push({
time: parseTimeFromLyric(lyric),
content: parseContentFromLyric(lyric),
});
});
cheerLyrics.forEach((lyric) => {
parsedCheerLyrics.push({
mode: lyric.mode,
time: parseTimeFromLyric(lyric),
content: parseContentFromLyric(lyric),
});
});
const originLength = parsedOriginLyrics.length;
const cheerLength = parsedCheerLyrics.length;
let i = 0, j = 0;
while (i < originLength && j < cheerLength) {
const $li = $("<li></li>");
// 根据时间设置歌词
if (parsedOriginLyrics[i].time <= parsedCheerLyrics[j].time) {
// 设置原曲歌词
$li.text(parsedOriginLyrics[i++].content).addClass("original");
} else {
// 设置打call歌词
$li.text(parsedCheerLyrics[j++].content).addClass("cheerful");
}
$ul.append($li);
}
// 追加结尾处歌词
while (i < originLength) {
const $li = $("<li></li>");
$li.text(parsedOriginLyrics[i++].content).addClass("original");
$ul.append($li);
}
while (j < cheerLength) {
const $li = $("<li></li>");
$li.text(parsedCheerLyrics[j++].content).addClass("cheerful");
$ul.append($li);
}
lyricContent.append($ul);
};
// 初始化操作入口
const initEntrance = () => {
const actor = $("#action-container");
const callImg = $("#call-img");
const modeButton = $("#mode");
const callButton = $("#call");
const imageSrc = IMAGE_SRC;
callImg.attr("src", imageSrc);
callImg.draggable();
callImg.click(() => {
actor.toggle(200);
});
callImg.hover(() => {
callImg.css("cursor", "pointer");
});
actor.hide();
actor.draggable();
initAudio(AUDIO_SRC);
initLyricContent(ORIGIN_LYRICS, CHEER_LYRICS);
callButton.click(() => {
isCalling = 1 - isCalling;
callButton.text(isCalling ? "发送中..." : "弹幕打Call");
});
modeButton.click(() => {
mode = (mode + 1) % 3;
modeButton.text(`模式${mode + 1}`);
});
};
initEntrance();
};
// 客户端请求
const apiClient = axios.create({
baseURL: "https://api.live.bilibili.com",
withCredentials: true,
});
// 获取勋章数据
let medalInfos = [];
try {
setTimeout(async () => {
const res = await apiClient
.get("/xlive/web-ucenter/user/MedalWall", {
params: {
target_id: window.__NEPTUNE_IS_MY_WAIFU__.userLabInfo.data.uid
}
});
medalInfos = res.data.data.list;
}, 1000);
} catch (e) {
console.warn("查看是否加入粉丝团时出错", e);
}
// 是否加入粉丝团
const filteredMedalInfo = medalInfos.filter((item) => {
return NANO_UID === item.medal_info.target_id;
});
const isNanoFan = filteredMedalInfo.length > 0;
// 获取房间id
const getRoomId = () => {
if (window.__NEPTUNE_IS_MY_WAIFU__) {
return window.__NEPTUNE_IS_MY_WAIFU__.roomInfoRes.data.room_info.room_id;
} else {
const url = document.URL;
const re = /\/\d+/.exec(url);
return re[0].substr(1);
}
};
const pattern = /(room|official)(_\d+){1,2}/;
const data = new FormData();
const roomId = getRoomId();
// 获取CsrfToken
const jct = document.cookie.match(/\bbili_jct=(.+?)(?:;|$)/)[1];
data.set("bubble", "0");
data.set("color", "16777215");
data.set("mode", "1");
data.set("fontsize", "25");
data.set("rnd", parseInt(Date.now() / 1000));
data.set("roomid", getRoomId());
data.set("csrf", jct);
data.set("csrf_token", jct);
// 发送弹幕
const sendMessage = (message) => {
if (data.has("dm_type")) {
data.delete("dm_type");
}
data.set("msg", message);
if (message.includes("👏")) {
if (roomId === NANO_ROOM_ID && isNanoFan) {
// 如果在nano直播间且已加入粉丝团则发送表情包
data.set("dm_type", "1");
data.set("msg", "room_22347054_1816")
} else {
// 否则替换掉
data.set("msg", message.replaceAll("👏", ""));
}
}
apiClient
.post("/msg/send", data)
.then((res) => {
if (res.data.code === 0) {
switch (res.data.msg) {
case "":
console.log("发送成功 - " + message);
break;
case "f":
console.warn("发送失败 - 包含B站屏蔽词: " + message);
break;
case "k":
console.warn("发送失败 - 包含直播间屏蔽词: " + message);
break;
case "same restriction":
console.warn("发送失败 该弹幕已被限制 请选择其它弹幕");
break;
case "max limit exceeded":
console.warn("发送失败 弹幕池达到上限");
break;
default:
console.warn("发送失败 - " + res.data.message);
console.warn(res)
console.warn(res.data)
}
} else {
console.warn("发送失败 - " + res.data.message);
}
})
.catch(() => {
console.warn("发送失败 - " + message);
});
};
setTimeout(() => {
setup();
initCheer();
}, 2000);
})();