forked from swee/MeowNex
Compare commits
178 commits
Author | SHA1 | Date | |
---|---|---|---|
47e780e802 | |||
1eb278e6ad | |||
dfaef0451a | |||
548dea5e87 | |||
f0c0767dac | |||
b73b9429e0 | |||
c88248783b | |||
20cefb7e0f | |||
ab68c7a7c1 | |||
15a8c81333 | |||
0b692bdcdd | |||
b88d26674f | |||
259b9fd6a0 | |||
94349e748f | |||
d985390749 | |||
0b98666ed8 | |||
aef7ae5c8d | |||
4575f20f8d | |||
d114d6a776 | |||
5c39fa931c | |||
5becae903a | |||
70f1e3224a | |||
0b4744452d | |||
51c589a9ee | |||
384380f9d2 | |||
336613b6ad | |||
2c39315403 | |||
ad965917df | |||
77c0e408fc | |||
4b14009ec7 | |||
597c086197 | |||
a46cbd0699 | |||
c316b296e3 | |||
43815170d3 | |||
879fb639a7 | |||
f818d8c68c | |||
66423c1002 | |||
d89fcca9a0 | |||
088cc86581 | |||
9d1b357b06 | |||
cfe002054c | |||
d5d5021265 | |||
ed135914da | |||
8d20cdc895 | |||
a8a6f499a5 | |||
ffd4df5c45 | |||
de0574c806 | |||
1abd2fcf49 | |||
d74ce22379 | |||
53e695b52e | |||
0205e67e3b | |||
464424363b | |||
126a5c8ccd | |||
5bc6107eba | |||
cf0d135d49 | |||
2ea3496c2a | |||
4e52d38a46 | |||
4b559b2082 | |||
5d37084aad | |||
d711c6a546 | |||
f3b53af89b | |||
6d4e9e2eb0 | |||
b07de9f3de | |||
c7a7c13a35 | |||
fd9f3eefc8 | |||
0b416c8321 | |||
572746b6f7 | |||
2861afbb33 | |||
b1d32c8192 | |||
888625a802 | |||
7b0ecfe589 | |||
657368fd77 | |||
738fe1d739 | |||
8268fa0940 | |||
6a9d92e03d | |||
bb2871fc77 | |||
88a3c6613c | |||
e26038e968 | |||
dc6a910fb1 | |||
a11ceecfd3 | |||
b5a7102c87 | |||
c35756b0aa | |||
446ead214c | |||
a3a0778048 | |||
a45796883e | |||
e39f9c3f94 | |||
aa649efb68 | |||
e03ad71e72 | |||
91eff68249 | |||
4ff1b7bcb8 | |||
14a4b303e4 | |||
a0ef352973 | |||
697a6d67fb | |||
c42fb303e1 | |||
0e7fba7f31 | |||
e3faae3ef7 | |||
19d9bebdac | |||
2c191b0262 | |||
30ba0acdd4 | |||
fb979adce6 | |||
e79a9b3aac | |||
159f884a21 | |||
78445c2d1f | |||
334fbea381 | |||
793a5ed08d | |||
8958941758 | |||
2a1e568111 | |||
edeadaca80 | |||
3d3ffd2367 | |||
5d87ef5c40 | |||
4ce0170f00 | |||
22f4824abb | |||
b80482f9ed | |||
fd433122dc | |||
e079fb10cd | |||
be7202d5a5 | |||
e1a7461369 | |||
c605ac2f4c | |||
fdcd44ef16 | |||
2a8f19f981 | |||
7578acff90 | |||
eb8e8e4aed | |||
e31069ccb7 | |||
b8c0350c1d | |||
6607cb4014 | |||
76c48571df | |||
37f93a5d94 | |||
62b6c04fc3 | |||
d9fcb5427c | |||
39bb76f3a5 | |||
3b63e14c2c | |||
5c8c219280 | |||
a1ee0b6cdf | |||
cdfd6b9d7b | |||
00e29ab908 | |||
d8ee864bae | |||
847994826d | |||
d0b488b863 | |||
c6258e1094 | |||
8b70a73199 | |||
16ebb8fed4 | |||
0e0567446e | |||
c40890918f | |||
34ba0c15f5 | |||
d43bf24270 | |||
5e0235919a | |||
d784694262 | |||
124dd1dcba | |||
8382731ef0 | |||
36c136dcc3 | |||
2f36c10042 | |||
4021636f70 | |||
6227e6f097 | |||
94120b0a69 | |||
4ac94fb1bf | |||
eb28603287 | |||
c357314230 | |||
5f353aa6e9 | |||
b8aadb83ad | |||
3ee06823b9 | |||
34f8e736a1 | |||
1d93c75057 | |||
33d0043f13 | |||
9becc678d3 | |||
cac9148ebb | |||
ab9ef3dda8 | |||
c985451d2a | |||
b74e79bef1 | |||
ead0d55ac6 | |||
fc1024958a | |||
635f99985f | |||
00b364287c | |||
8676242d11 | |||
a262545322 | |||
8b54fa9c7b | |||
e3cfd9087e | |||
773fcd1b5e | |||
1e5d2fc29b |
17 changed files with 448 additions and 99 deletions
15
.forgejo/workflows/build.yml
Normal file
15
.forgejo/workflows/build.yml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
name: Check syntax
|
||||||
|
on: [push,workflow_dispatch]
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: alpine
|
||||||
|
steps:
|
||||||
|
- name: Setup Alpine
|
||||||
|
uses: https://git.swee.codes/swee/setup-alpine@main
|
||||||
|
with:
|
||||||
|
additional: python3
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install JSHint
|
||||||
|
run: npm --global install jshint
|
||||||
|
- run: python3 -m py_compile sweebot.py
|
||||||
|
- run: jshint script.js
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2024 swee
|
Copyright (c) 2024-2025 SWEE.codes, Depresst O, and other MeowNexUS contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
Experimental bot for IRC written in Python
|
Experimental bot for IRC written in Python
|
||||||
|
|
||||||
This is the original bot idea.
|
This is the original bot idea.
|
||||||
|
|
||||||
|
Other variants:
|
||||||
|
* [Guilded](/swee/MeowNexGuilded)
|
||||||
|
* [Discord](/swee/MeowNexDiscord) (Not maintained often)
|
19
cc/give
19
cc/give
|
@ -1,21 +1,28 @@
|
||||||
from sys import argv
|
from sys import argv
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import re
|
||||||
conn = sqlite3.connect("/home/sweebotirc/sbirc.db")
|
conn = sqlite3.connect("/home/sweebotirc/sbirc.db")
|
||||||
database = conn.cursor()
|
database = conn.cursor()
|
||||||
def getperms(cloak: str):
|
def getperms(mask: str):
|
||||||
try:
|
try:
|
||||||
database.execute("SELECT * FROM users WHERE username = '"+ cloak + "';")
|
database.execute(f"SELECT * FROM users;")
|
||||||
output = database.fetchall()
|
output = database.fetchall()
|
||||||
return output[0][1]
|
for i in output:
|
||||||
except:
|
if re.match(i[0].replace("*", ".+"), mask):
|
||||||
|
return i[1]
|
||||||
return ''
|
return ''
|
||||||
if getperms(argv[2]) == "full":
|
except:
|
||||||
|
print(traceback.format_exc())
|
||||||
|
return ''
|
||||||
|
if argv[2] == "full":
|
||||||
if len(argv) == 5:
|
if len(argv) == 5:
|
||||||
if argv[3] == argv[2]:
|
if argv[3] == argv[2]:
|
||||||
print(argv[1] + ": You wanna give yourself permissions!?")
|
print(argv[1] + ": You wanna give yourself permissions!?")
|
||||||
else:
|
else:
|
||||||
perms = getperms(argv[3])
|
perms = getperms(argv[3])
|
||||||
if perms != "":
|
if argv[4] in perms:
|
||||||
|
print("The specified user already has these permissions.")
|
||||||
|
elif perms != "":
|
||||||
database.execute("UPDATE users SET perms = '" + perms + "," + argv[4] + "' WHERE username = '" + argv[3] + "';")
|
database.execute("UPDATE users SET perms = '" + perms + "," + argv[4] + "' WHERE username = '" + argv[3] + "';")
|
||||||
print(argv[1] + ": Successfully appended '" + argv[4] + "' to the permissions of " + argv[3])
|
print(argv[1] + ": Successfully appended '" + argv[4] + "' to the permissions of " + argv[3])
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
from random import choice
|
from random import choice
|
||||||
opinions = ["Oreos are better than Chips Ahoy!", "Human baka, be furry!", "Cereal goes before milk!", "Cereal goes before milk, but what if I pour cereal before bowl? Answer: Chaos!", "Protogens don't run on swap, 1TB of physical RAM!", "Generative AI sucks."]
|
opinions = ["Oreos are better than Chips Ahoy!", "Human baka, be furry!", "Cereal goes before milk!", "Cereal goes before milk, but what if I pour cereal before bowl? Answer: Chaos!", "Protogens don't run on swap, 1TB of physical RAM!", "Generative AI sucks.", "Y'know, we've all fought about cereal going before milk, but nobody discussed about if choccy powder goes before milk!! ;-;", "Everyone has two sides, a left side, and a right side. lol"]
|
||||||
print(choice(opinions))
|
print(choice(opinions))
|
32
cc/idtr14y
Normal file
32
cc/idtr14y
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# Gets some facts about Swee, and compare that with regular 14-year-olds I guess
|
||||||
|
|
||||||
|
from random import randint
|
||||||
|
from os import environ
|
||||||
|
import os
|
||||||
|
quotes = [
|
||||||
|
"I don't think regular 14 year olds would use IRC",
|
||||||
|
"I don't think regular 14 year olds would be a programmer",
|
||||||
|
"I don't think regular 14 year olds would use the internet properly",
|
||||||
|
"I don't think regular 14 year olds would be a silly goober",
|
||||||
|
"I don't think regular 14 year olds would put MeowNexUS cc's in helps",
|
||||||
|
"I don't think regular 14 year olds would identify as a cat",
|
||||||
|
"I don't think regular 14 year olds would actually be nice",
|
||||||
|
"I don't think regular 14 year olds would use... like anything but tiktok",
|
||||||
|
"I don't think regular 14 year olds would use linux",
|
||||||
|
"I don't think regular 14 year olds would own an android phone",
|
||||||
|
"I don't think regular 14 year olds would touch grass",
|
||||||
|
"I don't think regular 14 year olds would chat outside of Discord",
|
||||||
|
"I don't think regular 14 year olds would touch the terminal",
|
||||||
|
"I don't think regular 14 year olds would &`\?,`,);@!?>",
|
||||||
|
"I don't think regular 14 year olds would install a custom ROM",
|
||||||
|
"I don't think regular 14 year olds would call # \"pound\"",
|
||||||
|
"I don't think regular 14 year olds would be sober"
|
||||||
|
]
|
||||||
|
if not os.path.exists(os.path.expanduser("~/.MNCHOICE")):
|
||||||
|
open(os.path.expanduser("~/.MNCHOICE"), "w").write("-1")
|
||||||
|
e = randint(0, len(quotes)-1)
|
||||||
|
while int(open(os.path.expanduser("~/.MNCHOICE")).read()) == e:
|
||||||
|
e = randint(0, len(quotes)-1)
|
||||||
|
# environ["MNCHOICE"] = str(e)
|
||||||
|
open(os.path.expanduser("~/.MNCHOICE"), "w").write(str(e))
|
||||||
|
print(quotes[e])
|
2
cc/introduce_yourself
Normal file
2
cc/introduce_yourself
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
print("Am Meow NexUS.")
|
||||||
|
print("None can be more silly than Meow NexUS :3")
|
|
@ -1,4 +1,7 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
import sweecrypt
|
import sweecrypt
|
||||||
from sys import argv
|
from sys import argv
|
||||||
|
if argv[3][:2] == "-s":
|
||||||
|
print(sweecrypt.decrypt(" ".join(argv[4:]), int(argv[3][2:])))
|
||||||
|
else:
|
||||||
print(sweecrypt.decrypt(" ".join(argv[3:])))
|
print(sweecrypt.decrypt(" ".join(argv[3:])))
|
|
@ -1,4 +1,7 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
import sweecrypt
|
import sweecrypt
|
||||||
from sys import argv
|
from sys import argv
|
||||||
|
if argv[3][:2] == "-s":
|
||||||
|
print(sweecrypt.encrypt(" ".join(argv[4:]), int(argv[3][2:])))
|
||||||
|
else:
|
||||||
print(sweecrypt.encrypt(" ".join(argv[3:])))
|
print(sweecrypt.encrypt(" ".join(argv[3:])))
|
17
cc/status
Normal file
17
cc/status
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import requests, traceback
|
||||||
|
status = [1, 0, 0]
|
||||||
|
try:
|
||||||
|
e = requests.get("https://sugarcane.node.swee.codes")
|
||||||
|
status[1] = e.ok
|
||||||
|
except:
|
||||||
|
print(traceback.format_exc())
|
||||||
|
status[1] = 0
|
||||||
|
try:
|
||||||
|
e = requests.get("https://licorice-webmin.swee.codes")
|
||||||
|
status[2] = e.ok
|
||||||
|
except:
|
||||||
|
print(traceback.format_exc())
|
||||||
|
status[2] = 0
|
||||||
|
check = "✅"
|
||||||
|
x = "❌"
|
||||||
|
print(f"Status: ✅ peppermint (main), {check if status[1] else x} sugarcane (unused), {check if status[2] else x} licorice (AI)")
|
|
@ -11,6 +11,11 @@
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<a class="download" style="background: #027ef9;" title="Refresh stats" onclick="refresh();"><img src="https://swee.codes/icons/refresh.svg"></a>
|
<a class="download" style="background: #027ef9;" title="Refresh stats" onclick="refresh();"><img src="https://swee.codes/icons/refresh.svg"></a>
|
||||||
|
<hr>
|
||||||
|
<h1>Last AI Request:</h1>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<div width="100%" id="aichat">...</div>
|
||||||
</center>
|
</center>
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
23
docs/config.md
Normal file
23
docs/config.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Configure the bot for the channel. Requires the "full" perms. (will be allowed by chanops soon)
|
||||||
|
|
||||||
|
|
||||||
|
Use +FLAG to enable a disabled-by-default, and -FLAG vice versa.
|
||||||
|
|
||||||
|
|
||||||
|
Available flags:
|
||||||
|
* multiline - be able to print multiline output (enabled default)
|
||||||
|
* colonthree - make the bot say ":3" when someone's message starts with ":3" (enabled default)
|
||||||
|
* :3c - oh weawwy? :3c (Only reply to :3c) (DISABLED default, overriden by colonthree)
|
||||||
|
* links - Parse titles of links sent by users (DISABLED default)
|
||||||
|
* gemini - Only parse titles of `gemini://` links (DISABLED default)
|
||||||
|
* sed - parse sed expressions without the need of $sed command (DISABLED default)
|
||||||
|
* config - placeholder to determine existence of configuration, do not modify.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Syntax:
|
||||||
|
```
|
||||||
|
$config [FLAG] [FLAG] - Apply one or more flags
|
||||||
|
$config clear - Clear all flags
|
||||||
|
$config - list all flags in the channel
|
||||||
|
```
|
12
helps/config
12
helps/config
|
@ -1,11 +1 @@
|
||||||
Configure the bot for the channel. Requires the "full" perms. (will be allowed by chanops soon)
|
Documentation for $config can now be found in https://irc-bot.swee.codes/docs/config
|
||||||
Use +FLAG to enable a disabled-by-default, and -FLAG vice versa.
|
|
||||||
Available flags:
|
|
||||||
multiline - be able to print multiline output (enabled default)
|
|
||||||
colonthree - make the bot say ":3" when someone's message starts with ":3" (enabled default)
|
|
||||||
links - parse titles of links sent by users (DISABLED default)
|
|
||||||
(the config flag is a placeholder, do not change it)
|
|
||||||
syntax:
|
|
||||||
> $config [FLAG] [FLAG] - Apply one or more flags
|
|
||||||
> $config clear - Clear all flags
|
|
||||||
> $config - list all flags in the channel
|
|
|
@ -1 +1 @@
|
||||||
Pulls the latest version of sweeBot from its Git repository. requires the "git" permissions.
|
Pulls the latest version of MeowNexUS IRC from its Git repository. requires the "git" permissions.
|
6
helps/sed
Normal file
6
helps/sed
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Use the s/ sed expression with a user's message, the "sed" flag omits the need for prepending $sed
|
||||||
|
Examples:
|
||||||
|
* s/foo/bar - replace foo with bar
|
||||||
|
* s/foo/bar/2 - replace the 2nd match of foo to bar
|
||||||
|
* s/foo/bar/someone - replace foo with bar from a message composed by the nick "someone"
|
||||||
|
* s/foo/bar/g - replace ALL matches of foo to bar
|
16
script.js
16
script.js
|
@ -1,3 +1,4 @@
|
||||||
|
/*jshint esversion: 8 */
|
||||||
// Fetching the run value for the first time
|
// Fetching the run value for the first time
|
||||||
fetch ("run.txt")
|
fetch ("run.txt")
|
||||||
.then(x => x.text())
|
.then(x => x.text())
|
||||||
|
@ -9,19 +10,26 @@ fetch ("block.txt")
|
||||||
fetch ("link.txt")
|
fetch ("link.txt")
|
||||||
.then(x => x.text())
|
.then(x => x.text())
|
||||||
.then(y => document.getElementById("links").innerHTML = y);
|
.then(y => document.getElementById("links").innerHTML = y);
|
||||||
|
fetch ("lastquery.txt")
|
||||||
|
.then(x => x.text())
|
||||||
|
.then(y => document.getElementById("aichat").innerHTML = y);
|
||||||
async function refresh(){
|
async function refresh(){
|
||||||
// Refresh the HTML to show the spinners
|
// Refresh the HTML to show the spinners
|
||||||
document.getElementById("run").innerHTML = "..."
|
document.getElementById("run").innerHTML = "...";
|
||||||
document.getElementById("blocked").innerHTML = "..."
|
document.getElementById("blocked").innerHTML = "...";
|
||||||
document.getElementById("links").innerHTML = "..."
|
document.getElementById("links").innerHTML = "...";
|
||||||
|
document.getElementById("aichat").innerHTML = "...";
|
||||||
// Then fetch the values the same way as on the first part of the script.
|
// Then fetch the values the same way as on the first part of the script.
|
||||||
fetch ("run.txt")
|
fetch ("run.txt")
|
||||||
.then(x => x.text())
|
.then(x => x.text())
|
||||||
.then(y => document.getElementById("run").innerHTML = y)
|
.then(y => document.getElementById("run").innerHTML = y);
|
||||||
fetch ("block.txt")
|
fetch ("block.txt")
|
||||||
.then(x => x.text())
|
.then(x => x.text())
|
||||||
.then(y => document.getElementById("blocked").innerHTML = y);
|
.then(y => document.getElementById("blocked").innerHTML = y);
|
||||||
fetch ("link.txt")
|
fetch ("link.txt")
|
||||||
.then(x => x.text())
|
.then(x => x.text())
|
||||||
.then(y => document.getElementById("links").innerHTML = y);
|
.then(y => document.getElementById("links").innerHTML = y);
|
||||||
|
fetch ("lastquery.txt")
|
||||||
|
.then(x => x.text())
|
||||||
|
.then(y => document.getElementById("aichat").innerHTML = y);
|
||||||
}
|
}
|
328
sweebot.py
328
sweebot.py
|
@ -1,4 +1,4 @@
|
||||||
__version__ = "0.0.2 Funni update" + ". https://git.swee.codes/MeowNex"
|
__version__ = "1.0.1 AI update" + ". https://git.swee.codes/swee/MeowNex"
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
from time import sleep, time, ctime
|
from time import sleep, time, ctime
|
||||||
|
@ -10,16 +10,25 @@ from random import choice, randint as random, randrange
|
||||||
import traceback
|
import traceback
|
||||||
import threading
|
import threading
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from urllib.parse import urlparse, parse_qs
|
||||||
from requests import get, exceptions as rex
|
from requests import get, exceptions as rex
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from googleapiclient.discovery import build
|
from googleapiclient.discovery import build
|
||||||
|
import uuid
|
||||||
|
import ssl
|
||||||
|
import requests
|
||||||
|
AIurl = environ["AIurl"]
|
||||||
|
AIsession = requests.Session()
|
||||||
|
AIsession.auth = (environ["AIuser"], environ["AIpass"])
|
||||||
|
AImodel = environ["AImodel"] if "AImodel" in environ else "llama2"
|
||||||
run = 0
|
run = 0
|
||||||
block = 0
|
block = 0
|
||||||
parsed = 0
|
parsed = 0
|
||||||
|
lastquery = "None yet."
|
||||||
# Dashboard thread
|
# Dashboard thread
|
||||||
from flask import Flask, send_file
|
from flask import Flask, send_file, abort as abrt, redirect as redir
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
responses_ai = {} # {uuid: response}
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index_html():
|
def index_html():
|
||||||
|
@ -36,22 +45,52 @@ def parses():
|
||||||
@app.route('/script.js')
|
@app.route('/script.js')
|
||||||
def script_js():
|
def script_js():
|
||||||
return send_file("script.js", mimetype='application/javascript')
|
return send_file("script.js", mimetype='application/javascript')
|
||||||
|
@app.route('/lastquery.txt')
|
||||||
|
def lastquery_txt():
|
||||||
|
return str(lastquery)
|
||||||
|
@app.route('/docs/config')
|
||||||
|
def config_docs():
|
||||||
|
return redir("https://git.swee.codes/swee/MeowNex/src/branch/main/docs/config.md")
|
||||||
|
@app.route('/response/<uuidd>')
|
||||||
|
def ai_response_truncate(uuidd):
|
||||||
|
if uuidd in responses_ai:
|
||||||
|
res = responses_ai[uuidd]
|
||||||
|
return f'<title>AI response {uuidd}</title>\n<meta name="viewport" content="width=device-width, initial-scale=1.0">\n<link rel="stylesheet" href="https://swee.codes/style.css" type="text/css">\n<body><center><h1>AI response {uuidd}</h1><br><br><div class=code width="100%" style="word-wrap: break-word;white-space: pre;text-align: left;">' + res
|
||||||
|
else:
|
||||||
|
abrt(404)
|
||||||
threading.Thread(target=app.run, daemon=True, kwargs={"port": 2005}).start()
|
threading.Thread(target=app.run, daemon=True, kwargs={"port": 2005}).start()
|
||||||
|
|
||||||
|
# YouTube API
|
||||||
DEVELOPER_KEY = environ["ytapi"]
|
DEVELOPER_KEY = environ["ytapi"]
|
||||||
headers = {
|
headers = {
|
||||||
'User-Agent': 'SweeBot IRC ' + __version__
|
'User-Agent': 'MeowNexUS IRC ' + __version__
|
||||||
}
|
}
|
||||||
|
def get_yt_id(url):
|
||||||
|
query = urlparse(url)
|
||||||
|
# youtu.be already contains the ID in the path
|
||||||
|
if query.hostname == 'youtu.be': return query.path[1:]
|
||||||
|
if query.hostname in {'www.youtube.com', 'youtube.com', 'music.youtube.com'}:
|
||||||
|
# URLs that have the ID in the path instead of the query.
|
||||||
|
integrated_in_url = ["watch", "embed", "v", "shorts"]
|
||||||
|
try:
|
||||||
|
# The regular /watch path, which stores the ID in the query.
|
||||||
|
if query.path == '/watch': return parse_qs(query.query)['v'][0]
|
||||||
|
# Alternatively, it will get the ID in the path if the path was in the list above.
|
||||||
|
elif query.path.split('/')[1] in integrated_in_url: return query.path.split('/')[2]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
class config:
|
class config:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.conn = sqlite3.connect(environ["SBconfig"])
|
self.conn = sqlite3.connect(environ["SBconfig"])
|
||||||
self.database = self.conn.cursor()
|
self.database = self.conn.cursor()
|
||||||
def perms(self, cloak: str):
|
def perms(self, mask: str):
|
||||||
try:
|
try:
|
||||||
self.database.execute(f"SELECT * FROM users WHERE username = ?;", [cloak])
|
self.database.execute(f"SELECT * FROM users;")
|
||||||
output = self.database.fetchall()
|
output = self.database.fetchall()
|
||||||
return output[0][1]
|
for i in output:
|
||||||
|
if re.match(i[0].replace("*", ".+"), mask):
|
||||||
|
return i[1]
|
||||||
|
return ''
|
||||||
except:
|
except:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
return ''
|
return ''
|
||||||
|
@ -121,6 +160,11 @@ def humanbytes(B):
|
||||||
return '{0:.2f}GB'.format(B / GB)
|
return '{0:.2f}GB'.format(B / GB)
|
||||||
elif TB <= B:
|
elif TB <= B:
|
||||||
return '{0:.2f}TB'.format(B / TB)
|
return '{0:.2f}TB'.format(B / TB)
|
||||||
|
def rplce(text, old, new, n):
|
||||||
|
parts = text.split(old)
|
||||||
|
if len(parts) <= n:
|
||||||
|
return text # Not enough occurrences to replace
|
||||||
|
return old.join(parts[:n]) + new + old.join(parts[n:])
|
||||||
def replace_color_codes(text):
|
def replace_color_codes(text):
|
||||||
def replacer(match):
|
def replacer(match):
|
||||||
code = match.group(0)
|
code = match.group(0)
|
||||||
|
@ -171,7 +215,7 @@ class bot_irc:
|
||||||
|
|
||||||
self.irc_socket.send(
|
self.irc_socket.send(
|
||||||
bytes(
|
bytes(
|
||||||
"USER " + bot_nick + " " + bot_nick + " " + bot_nick + " :SweeBot, a very cool bot made by Swee :3\n",
|
"USER " + bot_nick + " " + bot_nick + " " + bot_nick + " :MeowNexUS, a very cool bot made by Swee :3\n",
|
||||||
"UTF-8",
|
"UTF-8",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -224,9 +268,13 @@ pats = ["-w-", "Meep...", "Prr!"]
|
||||||
meows_happy = ['Meow!', 'Nyaa~', 'Mrow.', 'Prr! :3', "Mrrp?", "Mreow.", "!woeM", "3: !rrP", "~aayN", "Mew!", "Moew!"]
|
meows_happy = ['Meow!', 'Nyaa~', 'Mrow.', 'Prr! :3', "Mrrp?", "Mreow.", "!woeM", "3: !rrP", "~aayN", "Mew!", "Moew!"]
|
||||||
meows_upset = ['Hiss!', "!ssiH", "Grrr..."]
|
meows_upset = ['Hiss!', "!ssiH", "Grrr..."]
|
||||||
my_self = ["MeowNexUS", "MeowNexU5", "MeowN3xUS"]
|
my_self = ["MeowNexUS", "MeowNexU5", "MeowN3xUS"]
|
||||||
|
logs = {} # {channel: [line, line]} max 10 lines
|
||||||
happiness = 5
|
happiness = 5
|
||||||
global times
|
global times
|
||||||
times = 0
|
times = 0
|
||||||
|
ai_storage = {}
|
||||||
|
ai_quotes = ["Oki lemme think about this one...", "Oki gimme a sec...", "Processing...", "Stand by...", "Meow..."]
|
||||||
|
emoticons = {";3": "I think you forgot to press shift", ":#": "Wait no, don't hold shift THAT long!"}
|
||||||
def irci2():
|
def irci2():
|
||||||
irc2.connect_irc(
|
irc2.connect_irc(
|
||||||
server_irc, port_irc, channel_irc, "sweeB0t", botpass_irc, botnickpass_irc + "/B"
|
server_irc, port_irc, channel_irc, "sweeB0t", botpass_irc, botnickpass_irc + "/B"
|
||||||
|
@ -290,6 +338,7 @@ irl2 = threading.Thread(target=irci2, daemon=True)
|
||||||
irl2.start()
|
irl2.start()
|
||||||
irl3 = threading.Thread(target=irci3, daemon=True)
|
irl3 = threading.Thread(target=irci3, daemon=True)
|
||||||
irl3.start()
|
irl3.start()
|
||||||
|
ticker=0
|
||||||
while True:
|
while True:
|
||||||
teext = irc.response_irc().split("\r\n")
|
teext = irc.response_irc().split("\r\n")
|
||||||
for text in teext:
|
for text in teext:
|
||||||
|
@ -304,8 +353,9 @@ while True:
|
||||||
channel = text.split("PRIVMSG")[1].split(" ")[1]
|
channel = text.split("PRIVMSG")[1].split(" ")[1]
|
||||||
nick = text.split(" ")[0][1:].split("!")[0]
|
nick = text.split(" ")[0][1:].split("!")[0]
|
||||||
username = text.split(" ")[0][1:].split("@")[1]
|
username = text.split(" ")[0][1:].split("@")[1]
|
||||||
|
mask = text.split(" ")[0][1:]
|
||||||
try:
|
try:
|
||||||
perms = sbconfig.perms(username)
|
perms = sbconfig.perms(mask)
|
||||||
except:
|
except:
|
||||||
perms = ""
|
perms = ""
|
||||||
print(command)
|
print(command)
|
||||||
|
@ -313,15 +363,65 @@ while True:
|
||||||
print(nick)
|
print(nick)
|
||||||
print(username)
|
print(username)
|
||||||
print(perms)
|
print(perms)
|
||||||
|
cont = " ".join(command)
|
||||||
|
if not channel in logs:
|
||||||
|
logs[channel] = [{"nick": nick, "content": cont}]
|
||||||
|
else:
|
||||||
|
logs[channel].append({"nick": nick, "content": cont})
|
||||||
|
if len(logs[channel]) > 128: logs[channel] = logs[channel][::-1][:128][::-1]
|
||||||
#open("log-text-"+channel, "a").write(" ".join(command) + "\n")
|
#open("log-text-"+channel, "a").write(" ".join(command) + "\n")
|
||||||
#open("log-name-"+channel, "a").write(nick + "\n")
|
#open("log-name-"+channel, "a").write(nick + "\n")
|
||||||
except:
|
except:
|
||||||
#print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
def replased(expression):
|
||||||
|
if channel in logs:
|
||||||
|
try:
|
||||||
|
if expression.split("/")[0].lower() != "s": raise IndexError()
|
||||||
|
find = expression.split("/")[1]
|
||||||
|
replace = expression.split("/")[2]
|
||||||
|
user = None
|
||||||
|
repeat = False
|
||||||
|
index = 1
|
||||||
|
try:
|
||||||
|
extraflags = expression.split("/")[3:]
|
||||||
|
for i in extraflags:
|
||||||
|
if i.strip() == "":
|
||||||
pass
|
pass
|
||||||
|
elif i.lower() == "g":
|
||||||
|
repeat = True
|
||||||
|
elif i.strip().isdigit():
|
||||||
|
print(f"index = {int(i)}")
|
||||||
|
index = int(i)
|
||||||
|
else:
|
||||||
|
print(f"user = {i.lower()}")
|
||||||
|
user = i.lower()
|
||||||
|
except: pass
|
||||||
|
cache = None
|
||||||
|
for i in logs[channel][::-1]:
|
||||||
|
if find in i["content"] and (user == None or i["nick"].lower() == user) and not "ignore" in i:
|
||||||
|
cache = i
|
||||||
|
break
|
||||||
|
if cache == None:
|
||||||
|
raise Exception("The specified text couldn't be found")
|
||||||
|
else:
|
||||||
|
if repeat:
|
||||||
|
cache["content"] = cache["content"].replace(find, replace)
|
||||||
|
else:
|
||||||
|
cache["content"] = rplce(cache["content"], find, replace, index)
|
||||||
|
cachenick = cache["nick"]
|
||||||
|
cachecontent = cache["content"]
|
||||||
|
multiline(f"[RPL] <{cachenick}> {cachecontent}", channel)
|
||||||
|
except IndexError:
|
||||||
|
irc.send_irc(channel, nick + ": [ERR] Sed expression might be incorrectly written!")
|
||||||
|
except Exception as ex:
|
||||||
|
irc.send_irc(channel, nick + ": [ERR] " + str(ex))
|
||||||
|
else:
|
||||||
|
irc.send_irc(channel, nick + ": [!!!] No logs saved in " + channel)
|
||||||
try:
|
try:
|
||||||
#if True:
|
#if True:
|
||||||
if "PRIVMSG" in text and not nick in my_self:
|
if "PRIVMSG" in text and (not "ignore" in sbconfig.perms(mask)) and not nick in my_self:
|
||||||
if "PRIVMSG" in text and command[0][0] == "$":
|
if "PRIVMSG" in text and command[0][0] == "$":
|
||||||
|
logs[channel] = logs[channel][:-1]
|
||||||
run+=1
|
run+=1
|
||||||
if command[0] == "$ping":
|
if command[0] == "$ping":
|
||||||
if random(1,2) == 1:
|
if random(1,2) == 1:
|
||||||
|
@ -353,9 +453,9 @@ while True:
|
||||||
|
|
||||||
elif command[0] == "$whoami":
|
elif command[0] == "$whoami":
|
||||||
if perms != "":
|
if perms != "":
|
||||||
irc.send_irc(channel, nick + ": " + username + " (Your cloak has permissions, use the 'perms' command to see)")
|
irc.send_irc(channel, nick + ": " + mask + " (Your hostmask has permissions, use the 'perms' command to see)")
|
||||||
else:
|
else:
|
||||||
irc.send_irc(channel, nick + ": " + username)
|
irc.send_irc(channel, nick + ": " + mask)
|
||||||
|
|
||||||
elif command[0] == "$welcome":
|
elif command[0] == "$welcome":
|
||||||
name = nick if not len(command) > 1 else " ".join(command[1:])
|
name = nick if not len(command) > 1 else " ".join(command[1:])
|
||||||
|
@ -367,9 +467,9 @@ while True:
|
||||||
elif command[0] == "$perms":
|
elif command[0] == "$perms":
|
||||||
if len(command) == 2:
|
if len(command) == 2:
|
||||||
if sbconfig.perms(command[1]) != "":
|
if sbconfig.perms(command[1]) != "":
|
||||||
irc.send_irc(channel, nick + ": permissions of cloak " + command[1] + ": " + sbconfig.perms(command[1]))
|
irc.send_irc(channel, nick + ": permissions of hostmask " + command[1] + ": " + sbconfig.perms(command[1]))
|
||||||
else:
|
else:
|
||||||
irc.send_irc(channel, nick + ": The cloak " + command[1] + " Doesn't have permissions.")
|
irc.send_irc(channel, nick + ": The hostmask wildcard " + command[1] + " Doesn't have permissions.")
|
||||||
else:
|
else:
|
||||||
if perms != "":
|
if perms != "":
|
||||||
irc.send_irc(channel, nick + ": " + perms)
|
irc.send_irc(channel, nick + ": " + perms)
|
||||||
|
@ -392,8 +492,7 @@ while True:
|
||||||
ossystem("git fetch")
|
ossystem("git fetch")
|
||||||
ossystem("git pull")
|
ossystem("git pull")
|
||||||
irc.send_irc(channel, nick + ": Pulled from Git, restarting bot...")
|
irc.send_irc(channel, nick + ": Pulled from Git, restarting bot...")
|
||||||
sleep(1)
|
restart()
|
||||||
ossystem("sudo systemctl restart sweebot")
|
|
||||||
else:
|
else:
|
||||||
irc.send_irc(channel, nick + ": Permission denied.")
|
irc.send_irc(channel, nick + ": Permission denied.")
|
||||||
block+=1
|
block+=1
|
||||||
|
@ -440,7 +539,49 @@ while True:
|
||||||
block+=1
|
block+=1
|
||||||
run-=1
|
run-=1
|
||||||
|
|
||||||
|
elif command[0] == "$ai-chat":
|
||||||
|
try:
|
||||||
|
|
||||||
|
multiline(choice(ai_quotes), channel)
|
||||||
|
prettylogs = ""
|
||||||
|
for i in logs[channel][-15:]:
|
||||||
|
prettylogs += i["nick"] + ": " + i["content"] + "\n"
|
||||||
|
prettylogs = prettylogs.strip()
|
||||||
|
chatquery = f"--Details--\nYour happiness level is {happiness}/10, your emotion level will impact the conversation's tone.\nYour name is MeowNexUS, you're a bot who acts like an anthropomorphic cat/furry\nYour beloved creator is named Swee.\nDo not start your reply with your name, people already know who you are.\nYou should not use ANY emojis at all, instead, use the much cuter ASCII emoticons and kaomojis such as :3\nIf the user's message contains ^ that means the person wants more details from the last message in the provided history.\nYou will be provided with the last 15 lines of this channel's chat logs to improve the conversation's context, Don't mind if your own messages have mutliple lines, and do not repeat any of the messages listed, it will be considered annoying.\nThe bottom of the chat history in the prompt will be the main question\n--Chat on {channel}--\n{prettylogs}\n--main question--\n{nick}: " + " ".join(command)
|
||||||
|
postAttempt = AIsession.post(AIurl, json={"model": AImodel, "prompt": chatquery, "stream": False})
|
||||||
|
print(postAttempt.content)
|
||||||
|
if not postAttempt.ok:
|
||||||
|
raise Exception("API Returned non-okay status code: " + postAttempt.status_code)
|
||||||
|
aimsg = postAttempt.json()["response"]
|
||||||
|
randomname = str(uuid.uuid4())
|
||||||
|
responses_ai[randomname] = aimsg
|
||||||
|
mtline = ""
|
||||||
|
lastquery = f"<p>Channel: {channel}</p><p>Request:</p><br><br><textarea class=code width=100% spellcheck=\"false\" autocapitalize=\"off\" autocomplete=\"off\" autocorrect=\"off\" readonly=\"true\">{chatquery}</textarea><hr><p>Response</p><br><br><textarea class=code width=100% spellcheck=\"false\" autocapitalize=\"off\" autocomplete=\"off\" autocorrect=\"off\" readonly=\"true\">{aimsg}</textarea>"
|
||||||
|
broke = False
|
||||||
|
logs[channel].append({"nick": nick, "content": " ".join(command)})
|
||||||
|
logs[channel].append({"nick": "MeowNexUS", "content": aimsg, "ignore": True})
|
||||||
|
for num, i in enumerate(aimsg.split("\n")):
|
||||||
|
if num == 5:
|
||||||
|
broke = True
|
||||||
|
break
|
||||||
|
elif len(i) > 256:
|
||||||
|
mtline += "\n" + i[:256] + "..."
|
||||||
|
broke = True
|
||||||
|
else:
|
||||||
|
mtline += "\n" + i
|
||||||
|
if broke:
|
||||||
|
mtline += f"\nView full response: https://irc-bot.swee.codes/response/{randomname}"
|
||||||
|
multiline(mtline, channel)
|
||||||
|
except Exception as ex:
|
||||||
|
multiline(f"Something went wrong while connecting to the AI server: {ex}", channel)
|
||||||
|
print(traceback.format_exc())
|
||||||
|
|
||||||
|
#elif command[0] == "$ai-clear":
|
||||||
|
# if channel in ai_storage:
|
||||||
|
# del ai_storage[channel]
|
||||||
|
# multiline("Done.", channel)
|
||||||
|
# else:
|
||||||
|
# multiline(f"There is no existing AI conversation in {channel}", channel)
|
||||||
elif command[0] == "$socket":
|
elif command[0] == "$socket":
|
||||||
if perms == "full":
|
if perms == "full":
|
||||||
if len(command) > 1:
|
if len(command) > 1:
|
||||||
|
@ -458,14 +599,24 @@ while True:
|
||||||
|
|
||||||
elif command[0] == "$patpat" or command[0] == "$headpat":
|
elif command[0] == "$patpat" or command[0] == "$headpat":
|
||||||
if len(command) == 2:
|
if len(command) == 2:
|
||||||
|
if int(command[1]) < 50:
|
||||||
for i in range(0,int(command[1])):
|
for i in range(0,int(command[1])):
|
||||||
happiness += (1 if happiness != 10 else 0)
|
happiness += (1 if happiness != 10 else 0)
|
||||||
|
else:
|
||||||
|
happiness = 10
|
||||||
elif len(command) == 1:
|
elif len(command) == 1:
|
||||||
happiness += (1 if happiness != 10 else 0)
|
happiness += (1 if happiness != 10 else 0)
|
||||||
|
if len(command) != 2 or int(command[1]) < 50:
|
||||||
multiline(choice(pats) + " (Emotion: Upset " +
|
multiline(choice(pats) + " (Emotion: Upset " +
|
||||||
("#" * int(happiness)) +
|
("#" * int(happiness)) +
|
||||||
("-" * int(10-happiness)) + " Happy)",
|
("-" * int(10-happiness)) + " Happy)",
|
||||||
channel)
|
channel)
|
||||||
|
else:
|
||||||
|
multiline("Okay that's enough!!" + " (Emotion: Upset " +
|
||||||
|
("#" * int(happiness)) +
|
||||||
|
("-" * int(10-happiness)) + " Happy)",
|
||||||
|
channel)
|
||||||
|
|
||||||
elif command[0] == "$emotion":
|
elif command[0] == "$emotion":
|
||||||
multiline("Emotion: Upset " +
|
multiline("Emotion: Upset " +
|
||||||
("#" * int(happiness)) +
|
("#" * int(happiness)) +
|
||||||
|
@ -473,14 +624,23 @@ while True:
|
||||||
channel)
|
channel)
|
||||||
elif command[0] == "$bap":
|
elif command[0] == "$bap":
|
||||||
if len(command) == 2:
|
if len(command) == 2:
|
||||||
|
if int(command[1]) < 50:
|
||||||
for i in range(0,int(command[1])):
|
for i in range(0,int(command[1])):
|
||||||
happiness -= (1 if happiness != 0 else 0)
|
happiness -= (1 if happiness != 0 else 0)
|
||||||
|
else:
|
||||||
|
happiness = 0
|
||||||
elif len(command) == 1:
|
elif len(command) == 1:
|
||||||
happiness -= (1 if happiness != 0 else 0)
|
happiness -= (1 if happiness != 0 else 0)
|
||||||
|
if len(command) != 2 or int(command[1]) < 50:
|
||||||
multiline(choice(baps) + " (Emotion: Upset " +
|
multiline(choice(baps) + " (Emotion: Upset " +
|
||||||
("#" * int(happiness)) +
|
("#" * int(happiness)) +
|
||||||
("-" * int(10-happiness)) + " Happy)",
|
("-" * int(10-happiness)) + " Happy)",
|
||||||
channel)
|
channel)
|
||||||
|
else:
|
||||||
|
multiline("Okay that's enough!!" + " (Emotion: Upset " +
|
||||||
|
("#" * int(happiness)) +
|
||||||
|
("-" * int(10-happiness)) + " Happy)",
|
||||||
|
channel)
|
||||||
elif command[0] == "$meow":
|
elif command[0] == "$meow":
|
||||||
if random(1,100) > (happiness*10):
|
if random(1,100) > (happiness*10):
|
||||||
multiline(choice(meows_upset), channel)
|
multiline(choice(meows_upset), channel)
|
||||||
|
@ -505,7 +665,7 @@ while True:
|
||||||
|
|
||||||
|
|
||||||
elif command[0] == "$version":
|
elif command[0] == "$version":
|
||||||
irc.send_irc(channel, "This is SweeBot " + __version__)
|
irc.send_irc(channel, "This is MeowNexUS IRC " + __version__)
|
||||||
|
|
||||||
elif command[0] == "$figlet":
|
elif command[0] == "$figlet":
|
||||||
if not sbconfig.cflagexist(channel, "-multiline"):
|
if not sbconfig.cflagexist(channel, "-multiline"):
|
||||||
|
@ -563,14 +723,10 @@ while True:
|
||||||
|
|
||||||
|
|
||||||
elif command[0] == "$sed":
|
elif command[0] == "$sed":
|
||||||
if len(command) > 1:
|
if len(command) == 2:
|
||||||
try:
|
replased(" ".join(command[1:]))
|
||||||
#if True:
|
|
||||||
raise Exception("WorkInProgress!!!")
|
|
||||||
except:
|
|
||||||
print(traceback.format_exc())
|
|
||||||
else:
|
else:
|
||||||
irc.send_irc(channel, nick + ": What to correct?")
|
irc.send_irc(channel, nick + ": [???] This command takes only one argument.")
|
||||||
|
|
||||||
|
|
||||||
elif command[0] == "$config":
|
elif command[0] == "$config":
|
||||||
|
@ -626,7 +782,7 @@ while True:
|
||||||
comm = command
|
comm = command
|
||||||
com.append("cc/" + comm[0][1:])
|
com.append("cc/" + comm[0][1:])
|
||||||
com.append(nick)
|
com.append(nick)
|
||||||
com.append(username)
|
com.append(perms)
|
||||||
comm.pop(0)
|
comm.pop(0)
|
||||||
for i in comm:
|
for i in comm:
|
||||||
com.append(i)
|
com.append(i)
|
||||||
|
@ -637,20 +793,50 @@ while True:
|
||||||
irc.send_irc(channel, nick + ": Command list under cc/debug: " + ", ".join(listdir("cc/" + command[0][1:])) + ".")
|
irc.send_irc(channel, nick + ": Command list under cc/debug: " + ", ".join(listdir("cc/" + command[0][1:])) + ".")
|
||||||
else:
|
else:
|
||||||
print(nick + ": Unrecognised command")
|
print(nick + ": Unrecognised command")
|
||||||
|
elif " ".join(command[0:3]).lower() == "i am meownexus":
|
||||||
|
irc.send_irc(channel, "No I am!")
|
||||||
|
elif " ".join(command[0:3]).lower() == "no i am!":
|
||||||
|
if ticker >= 5:
|
||||||
|
system(['figlet', 'NO I AM!'], channel)
|
||||||
|
ticker = 0
|
||||||
|
else:
|
||||||
|
irc.send_irc(channel, "No I am!")
|
||||||
|
ticker+=1
|
||||||
elif command[0] == ":3":
|
elif command[0] == ":3":
|
||||||
if not sbconfig.cflagexist(channel, "-colonthree"):
|
if not sbconfig.cflagexist(channel, "-colonthree"):
|
||||||
irc.send_irc(channel, ":3")
|
irc.send_irc(channel, ":3")
|
||||||
elif ":3c" in command:
|
elif command[0] in emoticons:
|
||||||
if not sbconfig.cflagexist(channel, "-colonthree"):
|
if not sbconfig.cflagexist(channel, "-colonthree"):
|
||||||
multiline(channel, choice(threes))
|
irc.send_irc(channel, emoticons[command[0]])
|
||||||
|
elif ":3c" in command:
|
||||||
|
if sbconfig.cflagexist(channel, "+:3c") or not sbconfig.cflagexist(channel, "-colonthree"):
|
||||||
|
multiline(choice(threes), channel)
|
||||||
|
elif command[0][:2].lower() == "s/":
|
||||||
|
logs[channel] = logs[channel][:-1]
|
||||||
|
if sbconfig.cflagexist(channel, "+sed"):
|
||||||
|
replased(" ".join(command))
|
||||||
# try to parse and find a link
|
# try to parse and find a link
|
||||||
|
|
||||||
if sbconfig.cflagexist(channel, "+links"):
|
if sbconfig.cflagexist(channel, "+links"):
|
||||||
try:
|
try:
|
||||||
for i in command:
|
for i in command:
|
||||||
if i[:8] == "https://":
|
parse = urlparse(i)
|
||||||
|
if parse.scheme in ["http", "https"]:
|
||||||
try:
|
try:
|
||||||
|
if parse.hostname in ["youtube.com", "youtu.be", "www.youtube.com", "m.youtube.com", "youtube-nocookie.com"] and get_yt_id(i) != None:
|
||||||
|
try:
|
||||||
|
video_id = get_yt_id(i)
|
||||||
|
youtube = build('youtube', 'v3', developerKey=DEVELOPER_KEY)
|
||||||
|
request = youtube.videos().list(part='snippet,statistics', id=video_id)
|
||||||
|
details = request.execute()
|
||||||
|
title = details['items'][0]['snippet']['title']
|
||||||
|
channel_yt = details['items'][0]['snippet']['channelTitle']
|
||||||
|
views = details['items'][0]['statistics']['viewCount']
|
||||||
|
multiline(f"({nick}) [▶️ YouTube] {title} | Author: {channel_yt} | {views} Views", channel)
|
||||||
|
except Exception as ex:
|
||||||
|
multiline("(" + nick + ") [YouTube Error, is it a valid YouTube URL?]", channel)
|
||||||
|
print(traceback.format_exc())
|
||||||
|
else:
|
||||||
e = get(i, headers=headers, timeout=10)
|
e = get(i, headers=headers, timeout=10)
|
||||||
header = e.headers
|
header = e.headers
|
||||||
content_type = header.get('content-type').split(";")[0]
|
content_type = header.get('content-type').split(";")[0]
|
||||||
|
@ -658,7 +844,7 @@ while True:
|
||||||
if content_type in allowedparse:
|
if content_type in allowedparse:
|
||||||
if e.ok:
|
if e.ok:
|
||||||
soup = BeautifulSoup(e.text, 'html.parser')
|
soup = BeautifulSoup(e.text, 'html.parser')
|
||||||
multiline("(" + nick + ") " + (" ".join(soup.title.string.splitlines())[:100] if soup.title != None else "[No title provided]"), channel)
|
multiline("(" + nick + ") " + (" ".join(soup.title.string.splitlines())[:256] if soup.title != None else "[No title provided]"), channel)
|
||||||
else:
|
else:
|
||||||
multiline("(" + nick + ") [HTTP " + str(e.status_code) + "]", channel)
|
multiline("(" + nick + ") [HTTP " + str(e.status_code) + "]", channel)
|
||||||
else:
|
else:
|
||||||
|
@ -668,22 +854,70 @@ while True:
|
||||||
multiline("(" + nick + ") [SSL Error: " + str(ex.message) + "]", channel)
|
multiline("(" + nick + ") [SSL Error: " + str(ex.message) + "]", channel)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
multiline("(" + nick + ") [Request error: " + str(ex.message) + "]", channel)
|
multiline("(" + nick + ") [Request error: " + str(ex.message) + "]", channel)
|
||||||
elif i[:7] == "http://":
|
|
||||||
e = get(i, headers=headers, timeout=10)
|
|
||||||
header = e.headers
|
|
||||||
content_type = header.get('content-type').split(";")[0]
|
|
||||||
content_len = header.get('Content-length')
|
|
||||||
if content_type in allowedparse:
|
|
||||||
if e.ok:
|
|
||||||
soup = BeautifulSoup(e.text, 'html.parser')
|
|
||||||
multiline("(" + nick + ") " + (" ".join(soup.title.string.splitlines())[:100] if soup.title != None else "[No title provided]"), channel)
|
|
||||||
else:
|
|
||||||
multiline("(" + nick + ") [HTTP " + str(e.status_code) + "]", channel)
|
|
||||||
else:
|
|
||||||
multiline("(" + nick + ") [" + humanbytes(content_len) + " " + str(content_type) + "]", channel)
|
|
||||||
parsed += 1
|
|
||||||
except:
|
except:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
if sbconfig.cflagexist(channel, "+links") or sbconfig.cflagexist(channel, "+gemini"):
|
||||||
|
try:
|
||||||
|
for i in command:
|
||||||
|
parse = urlparse(i)
|
||||||
|
unparsed = i
|
||||||
|
while True:
|
||||||
|
if parse.scheme == "gemini":
|
||||||
|
contx = ssl.create_default_context()
|
||||||
|
contx.check_hostname = False
|
||||||
|
contx.verify_mode = ssl.CERT_NONE
|
||||||
|
gsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
gemsocket = contx.wrap_socket(gsocket, server_hostname=parse.hostname)
|
||||||
|
gemsocket.connect((parse.hostname, 1965))
|
||||||
|
gemsocket.send(bytes(unparsed + "\r\n", "UTF-8"))
|
||||||
|
received = ""
|
||||||
|
while True:
|
||||||
|
gemresponse = gemsocket.recv(2048)
|
||||||
|
if gemresponse:
|
||||||
|
received += gemresponse.decode()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
received = received.replace("\r", "")
|
||||||
|
firstline = True
|
||||||
|
title = False
|
||||||
|
redirected = False
|
||||||
|
for i in received.split("\n"):
|
||||||
|
if firstline:
|
||||||
|
if i.split(" ")[0][0] == "3":
|
||||||
|
redirected = True
|
||||||
|
parsedd = urlparse(i.split(" ")[1])
|
||||||
|
unparsed = i.split(" ")[1]
|
||||||
|
break
|
||||||
|
elif i.split(" ")[0][0] != "2":
|
||||||
|
title = True
|
||||||
|
multiline("(" + nick + f") [{i}]", channel)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
firstline = False
|
||||||
|
if i.split(" ")[1].split(";")[0] != "text/gemini":
|
||||||
|
typee = i.split(" ")[1]
|
||||||
|
multiline("(" + nick + f") [Non-Gemtext file: {typee}]", channel)
|
||||||
|
title = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if i.strip()[0] == "#" and i.strip()[1] == " ":
|
||||||
|
print("Found title: " + i)
|
||||||
|
title = True
|
||||||
|
multiline("(" + nick + f") " + i.strip()[2:].strip(), channel)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if not title and not redirected:
|
||||||
|
multiline("(" + nick + ") [No title found]", channel)
|
||||||
|
if not redirected:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
except Exception as ex:
|
||||||
|
exc = str(ex)
|
||||||
|
print(traceback.format_exc())
|
||||||
|
multiline("(" + nick + f") [Request error: {exc}]", channel)
|
||||||
elif "JOIN" in text and "#nixsanctuary" in text:
|
elif "JOIN" in text and "#nixsanctuary" in text:
|
||||||
nick = text.split(":")[1].split("!")[0]
|
nick = text.split(":")[1].split("!")[0]
|
||||||
if not "Meow" in nick:
|
if not "Meow" in nick:
|
||||||
|
|
Loading…
Add table
Reference in a new issue