1
0
Fork 0
forked from swee/MeowNex

Compare commits

..

178 commits
main ... main

Author SHA1 Message Date
47e780e802 Update sweebot.py 2025-03-05 14:25:37 -08:00
1eb278e6ad Update sweebot.py 2025-03-05 14:23:29 -08:00
dfaef0451a Update LICENSE 2025-02-27 16:29:28 -08:00
548dea5e87 Update LICENSE 2025-02-27 16:29:00 -08:00
f0c0767dac Update helps/sed 2025-02-27 16:13:41 -08:00
b73b9429e0 Add helps/sed 2025-02-27 16:12:37 -08:00
c88248783b lol² 2025-02-27 09:24:31 -08:00
20cefb7e0f Update cc/idtr14y 2025-02-25 21:52:18 -08:00
ab68c7a7c1 Update cc/idtr14y 2025-02-25 21:49:43 -08:00
15a8c81333 Update cc/idtr14y 2025-02-25 21:39:06 -08:00
0b692bdcdd Update cc/idtr14y 2025-02-25 21:33:37 -08:00
b88d26674f Update cc/idtr14y 2025-02-25 21:33:03 -08:00
259b9fd6a0 Update cc/idtr14y 2025-02-25 21:32:22 -08:00
94349e748f Update cc/idtr14y 2025-02-25 21:31:58 -08:00
d985390749 Update cc/idtr14y 2025-02-25 21:31:19 -08:00
0b98666ed8 Update cc/idtr14y 2025-02-25 21:28:06 -08:00
aef7ae5c8d Add helps/idtr14y 2025-02-25 21:26:59 -08:00
4575f20f8d Update sweebot.py 2025-02-24 12:15:29 -08:00
d114d6a776 Update sweebot.py 2025-02-19 15:59:56 -08:00
5c39fa931c Update README.md 2025-02-19 13:43:07 -08:00
5becae903a Update cc/status 2025-02-12 19:35:39 -08:00
70f1e3224a Update cc/status 2025-02-12 19:35:20 -08:00
0b4744452d Update cc/status 2025-02-12 19:35:04 -08:00
51c589a9ee Update cc/status 2025-02-12 19:32:33 -08:00
384380f9d2 Add cc/status 2025-02-12 19:31:15 -08:00
336613b6ad Update sweebot.py 2025-02-07 17:01:10 -08:00
2c39315403 Update sweebot.py 2025-02-07 15:06:16 -08:00
ad965917df Update sweebot.py 2025-02-07 14:53:16 -08:00
77c0e408fc Update sweebot.py 2025-02-07 12:38:06 -08:00
4b14009ec7 Update sweebot.py 2025-02-06 23:04:39 -08:00
597c086197 Update sweebot.py 2025-02-06 23:00:33 -08:00
a46cbd0699 Update sweebot.py 2025-02-06 22:56:04 -08:00
c316b296e3 Update sweebot.py 2025-02-06 22:54:17 -08:00
43815170d3 Update sweebot.py 2025-02-06 22:49:29 -08:00
879fb639a7 Update sweebot.py 2025-02-06 22:45:22 -08:00
f818d8c68c Update sweebot.py 2025-02-06 22:37:35 -08:00
66423c1002 Update sweebot.py 2025-02-06 22:34:29 -08:00
d89fcca9a0 Update sweebot.py 2025-02-06 22:31:59 -08:00
088cc86581 Update sweebot.py 2025-02-06 22:31:07 -08:00
9d1b357b06 Update sweebot.py 2025-01-27 16:00:03 -08:00
cfe002054c Update sweebot.py 2025-01-26 22:37:19 -08:00
d5d5021265 Update sweebot.py 2025-01-26 22:35:58 -08:00
ed135914da Update sweebot.py 2025-01-26 22:34:17 -08:00
8d20cdc895 Update sweebot.py 2025-01-26 22:33:28 -08:00
a8a6f499a5 figlet haha 2025-01-26 22:30:04 -08:00
ffd4df5c45 Update sweebot.py 2025-01-26 22:16:24 -08:00
de0574c806 reverted
didnt work :(
2025-01-26 22:13:43 -08:00
1abd2fcf49 argument lol 2025-01-26 22:09:32 -08:00
d74ce22379 Update docs/config.md 2025-01-26 20:49:01 -08:00
53e695b52e Add cc/introduce_yourself 2025-01-26 20:38:36 -08:00
0205e67e3b Update sweebot.py 2025-01-26 10:13:21 -08:00
464424363b Delete .forgejo/workflows/JS.yml 2025-01-20 22:54:43 -08:00
126a5c8ccd Update .forgejo/workflows/JS.yml 2025-01-20 22:53:20 -08:00
5bc6107eba Upload files to ".forgejo/workflows" 2025-01-20 22:52:31 -08:00
cf0d135d49 Update .forgejo/workflows/build.yml 2025-01-20 22:48:39 -08:00
2ea3496c2a Update .forgejo/workflows/build.yml 2025-01-18 18:02:19 -08:00
4e52d38a46 Update .forgejo/workflows/build.yml 2025-01-18 18:01:09 -08:00
4b559b2082 Update .forgejo/workflows/build.yml 2025-01-18 17:59:50 -08:00
5d37084aad Update .forgejo/workflows/build.yml 2025-01-18 17:59:35 -08:00
d711c6a546 Update .forgejo/workflows/build.yml 2025-01-18 17:59:01 -08:00
f3b53af89b Update .forgejo/workflows/build.yml 2025-01-18 17:58:24 -08:00
6d4e9e2eb0 Update .forgejo/workflows/build.yml 2025-01-18 17:57:09 -08:00
b07de9f3de Update .forgejo/workflows/build.yml 2025-01-18 17:53:26 -08:00
c7a7c13a35 Update sweebot.py 2025-01-16 20:32:41 -08:00
fd9f3eefc8 Update sweebot.py 2025-01-16 20:31:04 -08:00
0b416c8321 Update sweebot.py 2025-01-16 20:29:45 -08:00
572746b6f7 Update sweebot.py 2025-01-16 20:28:38 -08:00
2861afbb33 Update sweebot.py 2025-01-16 20:27:49 -08:00
b1d32c8192 Update sweebot.py 2025-01-16 20:25:06 -08:00
888625a802 Update sweebot.py 2025-01-16 20:22:23 -08:00
7b0ecfe589 Update sweebot.py 2025-01-16 20:21:53 -08:00
657368fd77 Update sweebot.py 2025-01-16 20:21:39 -08:00
738fe1d739 Update sweebot.py 2025-01-16 20:16:54 -08:00
8268fa0940 Update sweebot.py 2025-01-16 20:13:54 -08:00
6a9d92e03d Update sweebot.py 2025-01-16 20:12:52 -08:00
bb2871fc77 Update sweebot.py 2025-01-12 21:01:12 -08:00
88a3c6613c Update sweebot.py 2025-01-12 21:00:30 -08:00
e26038e968 Update sweebot.py 2025-01-12 20:56:03 -08:00
dc6a910fb1 Update sweebot.py 2025-01-12 20:39:09 -08:00
a11ceecfd3 Update sweebot.py 2025-01-12 20:38:07 -08:00
b5a7102c87 Update sweebot.py 2025-01-12 20:37:01 -08:00
c35756b0aa Update sweebot.py 2025-01-12 20:36:40 -08:00
446ead214c Update sweebot.py 2025-01-12 20:35:44 -08:00
a3a0778048 Update sweebot.py 2025-01-12 20:34:47 -08:00
a45796883e Update sweebot.py 2025-01-12 20:32:31 -08:00
e39f9c3f94 Update sweebot.py 2025-01-12 20:24:03 -08:00
aa649efb68 Update sweebot.py 2025-01-12 20:21:41 -08:00
e03ad71e72 Update sweebot.py 2025-01-12 20:21:08 -08:00
91eff68249 Update sweebot.py 2025-01-12 20:20:07 -08:00
4ff1b7bcb8 Update sweebot.py 2025-01-12 20:18:31 -08:00
14a4b303e4 Update sweebot.py 2025-01-12 20:17:13 -08:00
a0ef352973 Update sweebot.py 2025-01-12 20:16:22 -08:00
697a6d67fb Update docs/config.md 2025-01-12 19:52:58 -08:00
c42fb303e1 Update sweebot.py 2024-12-30 16:51:05 -08:00
0e7fba7f31 Update sweebot.py 2024-12-30 16:49:41 -08:00
e3faae3ef7 Update sweebot.py 2024-12-30 16:49:27 -08:00
19d9bebdac Update sweebot.py 2024-12-30 16:32:07 -08:00
2c191b0262 Update sweebot.py 2024-12-30 16:28:40 -08:00
30ba0acdd4 Update sweebot.py 2024-12-30 16:26:49 -08:00
fb979adce6 Update sweebot.py 2024-12-30 16:22:30 -08:00
e79a9b3aac Update sweebot.py 2024-12-30 16:10:12 -08:00
159f884a21 Update sweebot.py 2024-12-30 16:06:48 -08:00
78445c2d1f Update sweebot.py 2024-12-28 21:09:37 -08:00
334fbea381 Update script.js 2024-12-28 20:59:26 -08:00
793a5ed08d Update dashboard.html 2024-12-28 20:57:57 -08:00
8958941758 Update sweebot.py 2024-12-28 20:56:44 -08:00
2a1e568111 Update sweebot.py 2024-12-28 20:38:30 -08:00
edeadaca80 Update sweebot.py 2024-12-28 20:37:21 -08:00
3d3ffd2367 Update sweebot.py 2024-12-28 20:36:44 -08:00
5d87ef5c40 Update sweebot.py 2024-12-28 20:35:45 -08:00
4ce0170f00 Update sweebot.py 2024-12-28 20:35:12 -08:00
22f4824abb Update sweebot.py 2024-12-28 20:34:12 -08:00
b80482f9ed Update sweebot.py 2024-12-28 20:33:02 -08:00
fd433122dc Update sweebot.py 2024-12-28 20:32:35 -08:00
e079fb10cd Update sweebot.py 2024-12-28 20:31:57 -08:00
be7202d5a5 Update cc/give 2024-12-28 18:44:08 -08:00
e1a7461369 Update cc/give 2024-12-28 18:43:35 -08:00
c605ac2f4c Update cc/give 2024-12-28 18:43:11 -08:00
fdcd44ef16 Update cc/give 2024-12-28 18:41:29 -08:00
2a8f19f981 Update sweebot.py 2024-12-28 18:40:51 -08:00
7578acff90 Update sweebot.py 2024-12-28 18:33:55 -08:00
eb8e8e4aed Update sweebot.py 2024-12-28 18:30:58 -08:00
e31069ccb7 Update sweebot.py 2024-12-28 18:27:44 -08:00
b8c0350c1d Update helps/pull 2024-12-27 01:04:13 -08:00
6607cb4014 Update sweebot.py 2024-12-27 01:03:15 -08:00
76c48571df Update sweebot.py 2024-12-27 00:58:57 -08:00
37f93a5d94 Update sweebot.py 2024-12-26 03:34:05 -08:00
62b6c04fc3 typo 2024-12-24 19:41:31 -08:00
d9fcb5427c Update cc/honest_opinion 2024-12-24 19:40:06 -08:00
39bb76f3a5 Update cc/sc-encode 2024-12-24 16:11:30 -08:00
3b63e14c2c Update cc/sc-decode 2024-12-24 16:11:23 -08:00
5c8c219280 Update cc/sc-decode 2024-12-24 16:10:34 -08:00
a1ee0b6cdf Update cc/sc-encode 2024-12-24 16:10:24 -08:00
cdfd6b9d7b Update cc/sc-encode 2024-12-24 16:10:16 -08:00
00e29ab908 Update cc/sc-decode 2024-12-24 16:09:16 -08:00
d8ee864bae Update sweebot.py 2024-12-23 16:16:41 -08:00
847994826d Update sweebot.py 2024-12-23 16:12:39 -08:00
d0b488b863 Update sweebot.py 2024-12-23 16:11:48 -08:00
c6258e1094 Update docs/config.md 2024-12-22 23:47:50 -08:00
8b70a73199 Update sweebot.py 2024-12-22 23:45:06 -08:00
16ebb8fed4 Update sweebot.py 2024-12-22 20:40:32 -08:00
0e0567446e Update sweebot.py 2024-12-22 20:39:00 -08:00
c40890918f Update sweebot.py 2024-12-22 20:37:39 -08:00
34ba0c15f5 Update helps/config 2024-12-22 19:59:57 -08:00
d43bf24270 Update sweebot.py 2024-12-22 19:59:02 -08:00
5e0235919a Add docs/config.md 2024-12-22 19:55:23 -08:00
d784694262 Update sweebot.py 2024-12-22 19:44:20 -08:00
124dd1dcba Update sweebot.py 2024-12-22 19:41:04 -08:00
8382731ef0 Update sweebot.py 2024-12-22 19:40:28 -08:00
36c136dcc3 Update sweebot.py 2024-12-22 19:40:05 -08:00
2f36c10042 Update sweebot.py 2024-12-22 19:33:37 -08:00
4021636f70 Update sweebot.py 2024-12-22 19:30:08 -08:00
6227e6f097 Update sweebot.py 2024-12-22 19:26:58 -08:00
94120b0a69 Update sweebot.py 2024-12-22 19:26:26 -08:00
4ac94fb1bf Update sweebot.py 2024-12-22 19:23:58 -08:00
eb28603287 Update sweebot.py 2024-12-22 19:21:28 -08:00
c357314230 fix typo 2024-12-22 19:18:28 -08:00
5f353aa6e9 Update sweebot.py 2024-12-22 19:17:53 -08:00
b8aadb83ad Update sweebot.py 2024-12-22 19:16:26 -08:00
3ee06823b9 Update sweebot.py 2024-12-22 19:15:29 -08:00
34f8e736a1 Update sweebot.py 2024-12-22 19:14:44 -08:00
1d93c75057 Update sweebot.py 2024-12-21 14:24:01 -08:00
33d0043f13 Update sweebot.py 2024-12-21 13:45:32 -08:00
9becc678d3 Update .forgejo/workflows/build.yml 2024-12-19 20:40:24 -08:00
cac9148ebb Update script.js 2024-12-18 16:33:47 -08:00
ab9ef3dda8 Update script.js 2024-12-18 16:32:37 -08:00
c985451d2a Update script.js 2024-12-18 16:30:36 -08:00
b74e79bef1 Update .forgejo/workflows/build.yml 2024-12-18 16:29:57 -08:00
ead0d55ac6 Update .forgejo/workflows/build.yml 2024-12-18 16:28:52 -08:00
fc1024958a Update .forgejo/workflows/build.yml 2024-12-18 16:27:20 -08:00
635f99985f Update .forgejo/workflows/build.yml 2024-12-18 16:26:07 -08:00
00b364287c Add .forgejo/workflows/build.yml 2024-12-18 16:25:17 -08:00
8676242d11 patch 2024-12-17 16:36:45 -08:00
a262545322 patch 2024-12-17 16:35:34 -08:00
8b54fa9c7b patch 2024-12-17 16:34:07 -08:00
e3cfd9087e patch 2024-12-17 16:29:34 -08:00
773fcd1b5e patch 2024-12-17 16:27:26 -08:00
1e5d2fc29b youtube 2024-12-17 16:24:56 -08:00
17 changed files with 448 additions and 99 deletions

View 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

View file

@ -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:

View file

@ -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
View file

@ -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:

View file

@ -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
View 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
View file

@ -0,0 +1,2 @@
print("Am Meow NexUS.")
print("None can be more silly than Meow NexUS :3")

View file

@ -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:])))

View file

@ -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
View 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)")

View file

@ -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
View 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
```

View file

@ -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

View file

@ -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
View 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

View file

@ -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);
} }

View file

@ -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: