Skip to content

Commit 256f977

Browse files
committed
fix syntax checks + add userscript.
1 parent 6612458 commit 256f977

3 files changed

Lines changed: 160 additions & 6 deletions

File tree

‎dccbot/app.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def __init__(self, config_file: str, bot_manager: IRCBotManager | None = None) -
248248
ircbot_logger = logging.getLogger("dccbot.ircbot")
249249
ircbot_logger.addHandler(ws_log_handler)
250250

251-
async def handle_ws_command(self, command: str, args: list[str], ws: web.WebSocketResponse) -> None:
251+
async def handle_ws_command(self, command: str | None, args: list[str], ws: web.WebSocketResponse) -> None:
252252
"""Handle a WebSocket command.
253253
254254
Args:
@@ -266,11 +266,11 @@ async def handle_ws_command(self, command: str, args: list[str], ws: web.WebSock
266266
if len(args) > 0:
267267
command = args.pop(0)
268268

269-
if command == 'part' or command == 'join':
269+
if command == "part" or command == "join":
270270
msg = f"Usage: {command} <server> <channel> [<channel> ...]"
271-
elif command == 'msg':
271+
elif command == "msg":
272272
msg = f"Usage: {command} <server> <target> <message>"
273-
elif command == 'msgjoin':
273+
elif command == "msgjoin":
274274
msg = f"Usage: {command} <server> <channel> <target> <message>"
275275
elif command:
276276
msg = f"Unknown command: {command}"

‎tests/test_app1.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ def fake_send_str(msg):
455455
record.msg = "Test log"
456456
record.args = ()
457457
record.created = datetime.datetime.now().timestamp()
458-
handler.format = lambda r: r.getMessage()
458+
handler.format = lambda r: r.getMessage() # type: ignore
459459

460460
handler.emit(record)
461461
# Check that the websocket received a JSON log message
@@ -480,7 +480,7 @@ async def test_websocket_log_handler_removes_closed_ws(monkeypatch):
480480
record = MagicMock()
481481
record.levelname = "WARNING"
482482
record.getMessage.return_value = "Closed test"
483-
handler.format = lambda r: r.getMessage()
483+
handler.format = lambda r: r.getMessage() # type: ignore
484484

485485
handler.emit(record)
486486
# ws_closed should be removed from handler.websockets

‎userscript/add-dccbot-btn.js‎

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// ==UserScript==
2+
// @name add-dccbot-btn
3+
// @namespace https://github.com/luni/dccbot/
4+
// @website https://github.com/luni/dccbot/
5+
// @version 2025-02-12
6+
// @description Add Button for DCCbot to automate downloads.
7+
// @author luni
8+
// @match https://www.xdcc.eu/search.php*
9+
// @match https://nibl.co.uk/*
10+
// @downloadURL https://raw.githubusercontent.com/luni/dccbot/refs/heads/main/userscript/add-dccbot-btn.js
11+
// @connect *
12+
// @grant GM_xmlhttpRequest
13+
// @grant GM_registerMenuCommand
14+
// @grant GM_getValue
15+
// @grant GM_setValue
16+
// ==/UserScript==
17+
18+
(function () {
19+
'use strict';
20+
21+
// Prompt user to set API endpoint
22+
GM_registerMenuCommand("Set API Endpoint", function () {
23+
const current = GM_getValue("dccbot_api", "");
24+
const endpoint = prompt("Enter DCCBot API endpoint:", current);
25+
if (endpoint !== null) {
26+
GM_setValue("dccbot_api", endpoint);
27+
alert("API endpoint saved: " + endpoint);
28+
}
29+
});
30+
31+
// Usage: fetch endpoint whenever needed
32+
const dccbot_api = GM_getValue("dccbot_api", "");
33+
if (!dccbot_api) {
34+
console.log("No API endpoint for DCCBot defined.");
35+
return
36+
}
37+
38+
console.log("API Endpoint for DCCBot: " + dccbot_api);
39+
40+
function get_element_by_xpath(path, parent) {
41+
return document.evaluate(path, parent || document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
42+
}
43+
44+
function get_elements_by_xpath(xpath, parent) {
45+
let results = [], query = document.evaluate(xpath, parent || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
46+
for (let i = 0, length = query.snapshotLength; i < length; ++i) { results.push(query.snapshotItem(i)); };
47+
return results;
48+
}
49+
50+
function send_msg(server, channel, user, message) {
51+
GM_xmlhttpRequest({
52+
method: "POST",
53+
url: dccbot_api + '/msg',
54+
headers: {
55+
"Content-Type": "application/json"
56+
},
57+
data: JSON.stringify({
58+
server: server,
59+
channel: channel,
60+
user: user,
61+
message: message
62+
}),
63+
onload: function (response) {
64+
console.log("[DCCBOT] API Reponse: " + response.responseText);
65+
}
66+
});
67+
}
68+
69+
function add_button_xdcc_eu() {
70+
document.getElementsByClassName('container')[0].style.maxWidth = "100%";
71+
document.getElementsByClassName('container')[0].style.width = "90%";
72+
document.getElementsByClassName('twelve')[0].style.marginTop = 0;
73+
74+
let all_results = [];
75+
for (let x of document.getElementById('table').getElementsByTagName('tbody')[0].getElementsByTagName('tr')) {
76+
let d = [
77+
x.getElementsByTagName('td')[1].getElementsByTagName('a')[0].href.replace('irc://', '').split('/')[0],
78+
];
79+
for (let y = 1; y < 4; y++) {
80+
d.push(x.getElementsByTagName('td')[y].textContent.trim());
81+
}
82+
d[3] = d[3].replace('#', '');
83+
all_results.push(d.join(';'))
84+
x.dataset.data = d.join(';');
85+
x.dataset.channel = d[1];
86+
x.dataset.server = d[0];
87+
x.dataset.bot = d[2];
88+
x.dataset.pack = d[3];
89+
let clmn = document.createElement('td'),
90+
btn = document.createElement('button');
91+
btn.innerHTML = 'Down';
92+
clmn.appendChild(btn);
93+
x.appendChild(clmn)
94+
btn.onclick = function (e) {
95+
e.preventDefault();
96+
const d = this.parentNode.parentNode.dataset;
97+
send_msg(d.server, d.channel, d.bot, "xdcc send " + d.pack);
98+
this.parentNode.parentNode.style.background = '#CECECE';
99+
return;
100+
};
101+
}
102+
103+
document.getElementsByTagName('h4')[0].onclick = function (e) {
104+
document.getElementById('msg').innerHTML = '<textarea style="width:100%;" rows=8>' + all_results.join('\n') + '</textarea>';
105+
}
106+
}
107+
108+
function add_button_nibl() {
109+
function send_to_dccbot(e) {
110+
e.preventDefault();
111+
const botpack = this.dataset.botpack,
112+
botname = this.dataset.botname;
113+
send_msg("irc.rizon.net", "#nibl", botname, "xdcc send " + botpack);
114+
115+
}
116+
117+
for (let copy_btn of get_elements_by_xpath("//button[contains(@class, 'copy-data')]")) {
118+
// const td=copy_btn.parentNode, new_btn=copy_btn.cloneNode();
119+
copy_btn.className = copy_btn.className.replace('copy-data ', '');
120+
copy_btn.innerHTML = 'Down';
121+
copy_btn.onclick = send_to_dccbot;
122+
// td.appendChild(new_btn);
123+
}
124+
125+
const copy_batch_btn = document.getElementById('copy-as-batch');
126+
copy_batch_btn.innerHTML = 'Download selected';
127+
copy_batch_btn.onclick = function (e) {
128+
e.preventDefault();
129+
let bots = {};
130+
for (const ckbox of get_elements_by_xpath("//input[@name='batch']")) {
131+
if (ckbox.checked) {
132+
if (!bots[ckbox.dataset.botname]) {
133+
bots[ckbox.dataset.botname] = [];
134+
}
135+
bots[ckbox.dataset.botname].push(ckbox.dataset.botpack);
136+
}
137+
}
138+
139+
for (const botname in bots) {
140+
send_msg("irc.rizon.net", "#nibl", botname, "xdcc batch " + bots[botname].join(','));
141+
}
142+
};
143+
}
144+
145+
const hostname = window.location.hostname;
146+
if (hostname == 'www.xdcc.eu') {
147+
add_button_xdcc_eu();
148+
return;
149+
}
150+
if (hostname == 'nibl.co.uk') {
151+
add_button_nibl();
152+
return;
153+
}
154+
})();

0 commit comments

Comments
 (0)