mirror of
https://github.com/Lynnesbian/FediBooks/
synced 2024-11-25 16:48:58 +00:00
Compare commits
24 commits
00369be990
...
1c67016fa6
Author | SHA1 | Date | |
---|---|---|---|
1c67016fa6 | |||
dc7787d296 | |||
fe01416134 | |||
8cab227531 | |||
4b6e563f76 | |||
07670c4a74 | |||
f1a4811094 | |||
570c62a779 | |||
39178dff9c | |||
d8dc54f802 | |||
e9cdbf7de2 | |||
3d0cdbc5e5 | |||
d48eb9264f | |||
5f089f4040 | |||
60728c0b35 | |||
170a666496 | |||
898f2f7aae | |||
841098cc18 | |||
34622230b0 | |||
11197eb7e7 | |||
9830eeda6b | |||
6cfa9ef35f | |||
fa60a6569d | |||
d06f89ed3f |
13 changed files with 201 additions and 76 deletions
|
@ -27,8 +27,7 @@ If this doesn't work, try using ``pip`` instead. If it still doesn't work, you m
|
||||||
```
|
```
|
||||||
CREATE DATABASE `fedibooks`;
|
CREATE DATABASE `fedibooks`;
|
||||||
CREATE USER 'myuser' IDENTIFIED BY 'mypassword';
|
CREATE USER 'myuser' IDENTIFIED BY 'mypassword';
|
||||||
GRANT USAGE ON *.* TO 'myuser'@localhost IDENTIFIED BY 'mypassword';
|
GRANT ALL PRIVILEGES ON `fedibooks`.* TO 'myuser';
|
||||||
GRANT ALL privileges ON `fedibooks`.* TO 'myuser'@localhost;
|
|
||||||
FLUSH PRIVILEGES;
|
FLUSH PRIVILEGES;
|
||||||
exit
|
exit
|
||||||
```
|
```
|
||||||
|
|
|
@ -34,24 +34,18 @@ def extract_post(post):
|
||||||
text = text.rstrip("\n") # remove trailing newline(s)
|
text = text.rstrip("\n") # remove trailing newline(s)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def make_post(args):
|
def generate_output(handle):
|
||||||
id = None
|
|
||||||
acct = None
|
|
||||||
if len(args) > 1:
|
|
||||||
id = args[1]
|
|
||||||
acct = args[3]
|
|
||||||
handle = args[0]
|
|
||||||
db = MySQLdb.connect(
|
db = MySQLdb.connect(
|
||||||
host = cfg['db_host'],
|
host = cfg['db_host'],
|
||||||
user=cfg['db_user'],
|
user=cfg['db_user'],
|
||||||
passwd=cfg['db_pass'],
|
passwd=cfg['db_pass'],
|
||||||
db=cfg['db_name']
|
db=cfg['db_name']
|
||||||
)
|
)
|
||||||
print("Generating post for {}".format(handle))
|
# print("Generating post for {}".format(handle))
|
||||||
dc = db.cursor(MySQLdb.cursors.DictCursor)
|
dc = db.cursor(MySQLdb.cursors.DictCursor)
|
||||||
c = db.cursor()
|
c = db.cursor()
|
||||||
dc.execute("""
|
dc.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
learn_from_cw,
|
learn_from_cw,
|
||||||
length,
|
length,
|
||||||
fake_mentions,
|
fake_mentions,
|
||||||
|
@ -64,17 +58,11 @@ def make_post(args):
|
||||||
FROM
|
FROM
|
||||||
bots, credentials
|
bots, credentials
|
||||||
WHERE
|
WHERE
|
||||||
bots.handle = %s
|
bots.handle = %s
|
||||||
AND bots.credentials_id = credentials.id
|
AND bots.credentials_id = credentials.id
|
||||||
""", (handle,))
|
""", (handle,))
|
||||||
|
|
||||||
bot = dc.fetchone()
|
bot = dc.fetchone()
|
||||||
client = Mastodon(
|
|
||||||
client_id = bot['client_id'],
|
|
||||||
client_secret = bot['client_secret'],
|
|
||||||
access_token = bot['secret'],
|
|
||||||
api_base_url = "https://{}".format(handle.split("@")[2])
|
|
||||||
)
|
|
||||||
|
|
||||||
# by default, only select posts that don't have CWs.
|
# by default, only select posts that don't have CWs.
|
||||||
# if learn_from_cw, then also select posts with CWs
|
# if learn_from_cw, then also select posts with CWs
|
||||||
|
@ -92,7 +80,7 @@ def make_post(args):
|
||||||
# 4. join the list into a string separated by newlines
|
# 4. join the list into a string separated by newlines
|
||||||
posts = "\n".join(list(sum(c.fetchall(), ())))
|
posts = "\n".join(list(sum(c.fetchall(), ())))
|
||||||
if len(posts) == 0:
|
if len(posts) == 0:
|
||||||
print("No posts to learn from.")
|
print("{} - No posts to learn from.".format(handle))
|
||||||
return
|
return
|
||||||
|
|
||||||
if bot['fake_mentions'] == 'never':
|
if bot['fake_mentions'] == 'never':
|
||||||
|
@ -124,30 +112,64 @@ def make_post(args):
|
||||||
if bot['fake_mentions_full']:
|
if bot['fake_mentions_full']:
|
||||||
post = re.sub(r"@(\w+)@([\w.]+)", r"@{}\1@{}\2".format(zws, zws), post)
|
post = re.sub(r"@(\w+)@([\w.]+)", r"@{}\1@{}\2".format(zws, zws), post)
|
||||||
else:
|
else:
|
||||||
post = re.sub(r"@(\w+)@([\w.]+)", r"@{}\1".format(zws), post)
|
post = re.sub(r"@(\w+)@([\w.]+)", r"@{}\1".format(zws), post)
|
||||||
# also format handles without instances, e.g. @user instead of @user@instan.ce
|
# also format handles without instances, e.g. @user instead of @user@instan.ce
|
||||||
post = re.sub(r"(?<!\S)@(\w+)", r"@{}\1".format(zws), post)
|
post = re.sub(r"(?<!\S)@(\w+)", r"@{}\1".format(zws), post)
|
||||||
|
|
||||||
print(post)
|
return bot, post
|
||||||
visibility = bot['post_privacy'] if len(args) == 1 else args[2]
|
|
||||||
visibilities = ['public', 'unlisted', 'private']
|
|
||||||
if visibilities.index(visibility) < visibilities.index(bot['post_privacy']):
|
|
||||||
# if post_privacy is set to a more restricted level than the visibility of the post we're replying to, use the user's setting
|
|
||||||
visibility = bot['post_privacy']
|
|
||||||
if acct is not None:
|
|
||||||
post = "{} {}".format(acct, post)
|
|
||||||
|
|
||||||
# ensure post isn't longer than bot['length']
|
|
||||||
post = post[:bot['length']]
|
def make_post(args):
|
||||||
# send toot!!
|
id = None
|
||||||
try:
|
acct = None
|
||||||
client.status_post(post, id, visibility = visibility, spoiler_text = bot['content_warning'])
|
if len(args) > 1:
|
||||||
except MastodonUnauthorizedError:
|
id = args[1]
|
||||||
# user has revoked the token given to the bot
|
acct = args[3]
|
||||||
# this needs to be dealt with properly later on, but for now, we'll just disable the bot
|
handle = args[0]
|
||||||
c.execute("UPDATE bots SET enabled = FALSE WHERE handle = %s", (handle,))
|
|
||||||
|
# print("Generating post for {}".format(handle))
|
||||||
|
|
||||||
|
bot, post = generate_output(handle)
|
||||||
|
|
||||||
|
client = Mastodon(
|
||||||
|
client_id = bot['client_id'],
|
||||||
|
client_secret = bot['client_secret'],
|
||||||
|
access_token = bot['secret'],
|
||||||
|
api_base_url = "https://{}".format(handle.split("@")[2])
|
||||||
|
)
|
||||||
|
|
||||||
|
db = MySQLdb.connect(
|
||||||
|
host = cfg['db_host'],
|
||||||
|
user=cfg['db_user'],
|
||||||
|
passwd=cfg['db_pass'],
|
||||||
|
db=cfg['db_name']
|
||||||
|
)
|
||||||
|
c = db.cursor()
|
||||||
|
|
||||||
|
# print(post)
|
||||||
|
visibility = bot['post_privacy'] if len(args) == 1 else args[2]
|
||||||
|
visibilities = ['public', 'unlisted', 'private']
|
||||||
|
if visibilities.index(visibility) < visibilities.index(bot['post_privacy']):
|
||||||
|
# if post_privacy is set to a more restricted level than the visibility of the post we're replying to, use the user's setting
|
||||||
|
visibility = bot['post_privacy']
|
||||||
|
if acct is not None:
|
||||||
|
post = "{} {}".format(acct, post)
|
||||||
|
|
||||||
|
# ensure post isn't longer than bot['length']
|
||||||
|
# TODO: ehhhhhhhhh
|
||||||
|
post = post[:bot['length']]
|
||||||
|
# send toot!!
|
||||||
|
try:
|
||||||
|
client.status_post(post, id, visibility = visibility, spoiler_text = bot['content_warning'])
|
||||||
|
except MastodonUnauthorizedError:
|
||||||
|
# user has revoked the token given to the bot
|
||||||
|
# this needs to be dealt with properly later on, but for now, we'll just disable the bot
|
||||||
|
c.execute("UPDATE bots SET enabled = FALSE WHERE handle = %s", (handle,))
|
||||||
|
except:
|
||||||
|
print("Failed to create post for {}".format(handle))
|
||||||
|
|
||||||
if id == None:
|
if id == None:
|
||||||
# this wasn't a reply, it was a regular post, so update the last post date
|
# this wasn't a reply, it was a regular post, so update the last post date
|
||||||
c.execute("UPDATE bots SET last_post = CURRENT_TIMESTAMP() WHERE handle = %s", (handle,))
|
c.execute("UPDATE bots SET last_post = CURRENT_TIMESTAMP() WHERE handle = %s", (handle,))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
c.close()
|
||||||
|
|
|
@ -47,7 +47,7 @@ def bot_accounts_add(mysql, cfg):
|
||||||
else:
|
else:
|
||||||
session['instance_type'] = "Mastodon"
|
session['instance_type'] = "Mastodon"
|
||||||
session['step'] += 1
|
session['step'] += 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = "Unsupported instance type. Misskey support is planned."
|
error = "Unsupported instance type. Misskey support is planned."
|
||||||
return render_template("bot/accounts_add.html", error = error)
|
return render_template("bot/accounts_add.html", error = error)
|
||||||
|
@ -81,12 +81,13 @@ def bot_accounts_add(mysql, cfg):
|
||||||
username = client.account_verify_credentials()['username']
|
username = client.account_verify_credentials()['username']
|
||||||
if username != session['username']:
|
if username != session['username']:
|
||||||
error = "Please authenticate as {}.".format(session['username'])
|
error = "Please authenticate as {}.".format(session['username'])
|
||||||
|
print("Auth error - {} is not {}".format(session['username'], username))
|
||||||
return render_template("bot/accounts_add.html", error = error)
|
return render_template("bot/accounts_add.html", error = error)
|
||||||
except:
|
except:
|
||||||
session['step'] = 1
|
session['step'] = 1
|
||||||
error = "Authentication failed."
|
error = "Authentication failed."
|
||||||
return render_template("bot/accounts_add.html", error = error)
|
return render_template("bot/accounts_add.html", error = error)
|
||||||
|
|
||||||
# 1. download host-meta to find webfinger URL
|
# 1. download host-meta to find webfinger URL
|
||||||
r = requests.get("https://{}/.well-known/host-meta".format(session['instance']), timeout=10)
|
r = requests.get("https://{}/.well-known/host-meta".format(session['instance']), timeout=10)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
|
|
|
@ -19,7 +19,7 @@ def scrape_posts(account):
|
||||||
)
|
)
|
||||||
handle = account[0]
|
handle = account[0]
|
||||||
outbox = account[1]
|
outbox = account[1]
|
||||||
print("Scraping {}".format(handle))
|
# print("Scraping {}".format(handle))
|
||||||
c = db.cursor()
|
c = db.cursor()
|
||||||
last_post = 0
|
last_post = 0
|
||||||
c.execute("SELECT COUNT(*) FROM `posts` WHERE `fedi_id` = %s", (handle,))
|
c.execute("SELECT COUNT(*) FROM `posts` WHERE `fedi_id` = %s", (handle,))
|
||||||
|
@ -80,9 +80,15 @@ def scrape_posts(account):
|
||||||
|
|
||||||
if not done:
|
if not done:
|
||||||
if pleroma:
|
if pleroma:
|
||||||
r = requests.get(j['next'], timeout = 10)
|
if 'next' in j:
|
||||||
|
r = requests.get(j['next'], timeout = 10)
|
||||||
|
else:
|
||||||
|
done = True
|
||||||
else:
|
else:
|
||||||
r = requests.get(j['prev'], timeout = 10)
|
if 'prev' in j:
|
||||||
|
r = requests.get(j['prev'], timeout = 10)
|
||||||
|
else:
|
||||||
|
done = True
|
||||||
|
|
||||||
if r.status_code == 429:
|
if r.status_code == 429:
|
||||||
# we are now being ratelimited, move on to the next user
|
# we are now being ratelimited, move on to the next user
|
||||||
|
@ -94,7 +100,7 @@ def scrape_posts(account):
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
print("Finished scraping {}".format(handle))
|
# print("Finished scraping {}".format(handle))
|
||||||
|
|
||||||
print("Establishing DB connection")
|
print("Establishing DB connection")
|
||||||
db = MySQLdb.connect(
|
db = MySQLdb.connect(
|
||||||
|
|
|
@ -2,33 +2,55 @@
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
from mastodon import Mastodon
|
from mastodon import Mastodon
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
|
import requests
|
||||||
import json
|
import json
|
||||||
import functions
|
import functions
|
||||||
|
|
||||||
cfg = json.load(open('config.json'))
|
cfg = json.load(open('config.json'))
|
||||||
|
|
||||||
def update_icon(bot):
|
def update_icon(bot):
|
||||||
db = MySQLdb.connect(
|
try:
|
||||||
host = cfg['db_host'],
|
db = MySQLdb.connect(
|
||||||
user=cfg['db_user'],
|
host = cfg['db_host'],
|
||||||
passwd=cfg['db_pass'],
|
user=cfg['db_user'],
|
||||||
db=cfg['db_name'],
|
passwd=cfg['db_pass'],
|
||||||
use_unicode=True,
|
db=cfg['db_name'],
|
||||||
charset="utf8mb4"
|
use_unicode=True,
|
||||||
)
|
charset="utf8mb4"
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
print("Failed to connect to database.")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
url = "https://{}".format(bot['handle'].split("@")[2])
|
||||||
|
try:
|
||||||
|
r = requests.head(url, timeout=10, allow_redirects = True)
|
||||||
|
if r.status_code != 200:
|
||||||
|
raise
|
||||||
|
except:
|
||||||
|
print("{} is down.".format(url))
|
||||||
|
return
|
||||||
|
|
||||||
print("Updating cached icon for {}".format(bot['handle']))
|
|
||||||
client = Mastodon(
|
client = Mastodon(
|
||||||
client_id = bot['client_id'],
|
client_id = bot['client_id'],
|
||||||
client_secret = bot['client_secret'],
|
client_secret = bot['client_secret'],
|
||||||
access_token = bot['secret'],
|
access_token = bot['secret'],
|
||||||
api_base_url = "https://{}".format(bot['handle'].split("@")[2])
|
api_base_url = url
|
||||||
)
|
)
|
||||||
|
|
||||||
avatar = client.account_verify_credentials()['avatar']
|
|
||||||
c = db.cursor()
|
c = db.cursor()
|
||||||
|
try:
|
||||||
|
avatar = client.account_verify_credentials()['avatar']
|
||||||
|
except:
|
||||||
|
c.execute("UPDATE bots SET icon_update_time = CURRENT_TIMESTAMP() WHERE handle = %s", (bot['handle'],))
|
||||||
|
db.commit()
|
||||||
|
c.close()
|
||||||
|
return
|
||||||
c.execute("UPDATE bots SET icon = %s, icon_update_time = CURRENT_TIMESTAMP() WHERE handle = %s", (avatar, bot['handle']))
|
c.execute("UPDATE bots SET icon = %s, icon_update_time = CURRENT_TIMESTAMP() WHERE handle = %s", (avatar, bot['handle']))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
c.close()
|
||||||
|
|
||||||
print("Establishing DB connection")
|
print("Establishing DB connection")
|
||||||
db = MySQLdb.connect(
|
db = MySQLdb.connect(
|
||||||
|
@ -48,6 +70,7 @@ db.commit()
|
||||||
|
|
||||||
print("Generating posts")
|
print("Generating posts")
|
||||||
cursor.execute("SELECT handle FROM bots WHERE enabled = TRUE AND TIMESTAMPDIFF(MINUTE, last_post, CURRENT_TIMESTAMP()) >= post_frequency")
|
cursor.execute("SELECT handle FROM bots WHERE enabled = TRUE AND TIMESTAMPDIFF(MINUTE, last_post, CURRENT_TIMESTAMP()) >= post_frequency")
|
||||||
|
# cursor.execute("SELECT handle FROM bots WHERE enabled = TRUE")
|
||||||
bots = cursor.fetchall()
|
bots = cursor.fetchall()
|
||||||
|
|
||||||
with Pool(cfg['service_threads']) as p:
|
with Pool(cfg['service_threads']) as p:
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 8.9 KiB |
44
app/static/script.js
Normal file
44
app/static/script.js
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
var chatlog = [];
|
||||||
|
|
||||||
|
function sendMessage() {
|
||||||
|
let id = window.location.href.split("/").slice(-1)[0]
|
||||||
|
message = document.getElementById("chatbox-input-box").value
|
||||||
|
document.getElementById("chatbox-input-box").value = ''
|
||||||
|
document.getElementById("chatbox-input-box").disabled = true;
|
||||||
|
chatlog.push(["user", message])
|
||||||
|
renderChatlog();
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4) {
|
||||||
|
if (this.status == 200) {
|
||||||
|
message = this.responseText.replace("\n", "<br>");
|
||||||
|
} else {
|
||||||
|
message = "Encountered an error while trying to get a response.";
|
||||||
|
}
|
||||||
|
chatlog.push(["bot", message]);
|
||||||
|
renderChatlog();
|
||||||
|
document.getElementById("chatbox-input-box").disabled = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhttp.open("GET", `/bot/chat/${id}/message`, true);
|
||||||
|
xhttp.send();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderChatlog() {
|
||||||
|
let chatbox = document.getElementById("chatbox");
|
||||||
|
let out = "";
|
||||||
|
if (chatlog.length > 50) {
|
||||||
|
chatlog.shift(); //only keep the 50 most recent messages to avoid slowdown
|
||||||
|
}
|
||||||
|
chatlog.forEach(function(item, i) {
|
||||||
|
if (item[0] == "user") {
|
||||||
|
out += `<div class="message-container user"><div class="message user">${item[1]}</div></div>`;
|
||||||
|
} else {
|
||||||
|
out += `<div class="message-container bot"><div class="bot-icon"></div><div class="message bot">${item[1]}</div></div>`;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
chatbox.innerHTML = out;
|
||||||
|
chatbox.scrollTop = chatbox.scrollHeight;
|
||||||
|
}
|
|
@ -217,21 +217,29 @@ form .row {
|
||||||
height: 90vh;
|
height: 90vh;
|
||||||
background-color: #3d4353;
|
background-color: #3d4353;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
#chatbox-input, #chatbox-input input{
|
#chatbox-input, #chatbox-input input{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
#chatbox, #chatbox-input {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
#chatbox-input {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
.message {
|
.message {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
max-width: 60%;
|
max-width: 60%;
|
||||||
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
.message-container.user {
|
.message-container.user {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.message-container .bot-icon {
|
.message-container .bot-icon {
|
||||||
background: center / contain url("https://lynnesbian.space/img/bune.png") no-repeat;
|
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
|
@ -4,6 +4,17 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>FediBooks</title>
|
<title>FediBooks</title>
|
||||||
{% include 'imports.html' %}
|
{% include 'imports.html' %}
|
||||||
|
<style>
|
||||||
|
.bot-icon {
|
||||||
|
background: center / contain url("{{icon}}") no-repeat;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
window.onload = function() {
|
||||||
|
document.getElementById("chatbox-input-box").focus();
|
||||||
|
document.getElementById("chatbox-input").onsubmit = sendMessage;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -11,7 +22,7 @@
|
||||||
<h1 class="thin centred">Chat</h1>
|
<h1 class="thin centred">Chat</h1>
|
||||||
<p class="centred">Talking to {{ bot }}</p>
|
<p class="centred">Talking to {{ bot }}</p>
|
||||||
<p class="centred" style="margin: 20px 0;">
|
<p class="centred" style="margin: 20px 0;">
|
||||||
<a class="button btn-primary" href="/bot/accounts/add" role="button"><i class="fas fa-home"></i> Home</a>
|
<a class="button btn-primary" href="/" role="button"><i class="fas fa-home"></i> Home</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -23,17 +34,11 @@
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div id="chatbox">
|
<div id="chatbox">
|
||||||
<div class="message-container user">
|
|
||||||
<div class="message user">Henlo</div>
|
|
||||||
</div>
|
|
||||||
<div class="message-container bot">
|
|
||||||
<div class="bot-icon"></div>
|
|
||||||
<div class="message bot">Henlo human uwu<br>How are you</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form id="chatbox-input">
|
<form id="chatbox-input">
|
||||||
<input name="message" placeholder="Press enter to send">
|
<input id="chatbox-input-box" autocomplete="off" required name="message" placeholder="Press enter to send">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% include 'error.html' %}
|
{% include 'error.html' %}
|
||||||
|
|
||||||
<div class="container centred">
|
<div class="container centred">
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
{% if session['step'] == 1 %}
|
{% if session['step'] == 1 %}
|
||||||
|
@ -26,12 +26,12 @@
|
||||||
|
|
||||||
{% elif session['step'] == 3 %}
|
{% elif session['step'] == 3 %}
|
||||||
<p>You now need to give your bot access to the {{ session['instance'] }} account you have created for it. If you have not yet created an account on {{ session['instance'] }} for your bot to use, please do so now.</p>
|
<p>You now need to give your bot access to the {{ session['instance'] }} account you have created for it. If you have not yet created an account on {{ session['instance'] }} for your bot to use, please do so now.</p>
|
||||||
<p>Sign in to the {{ session['instance'] }} account you want your bot to use, then click next to begin the authorisation process.</p>
|
<p>In another tab, sign in to the {{ session['instance'] }} account you want your bot to use. Once that's done, click next to begin the authorisation process.</p>
|
||||||
|
|
||||||
{% elif session['step'] == 4 %}
|
{% elif session['step'] == 4 %}
|
||||||
<h2 class="thin centred">Congratulations!</h2>
|
<h2 class="thin centred">Congratulations!</h2>
|
||||||
<p>FediBooks has successfully authenticated with your instance, and your bot is ready to be configured. Click finish to return to the bot management screen.</p>
|
<p>FediBooks has successfully authenticated with your instance, and your bot is ready to be configured. Click finish to return to the bot management screen.</p>
|
||||||
<p>To get your bot working, you need to add at least one account for it to learn from. You can do so by clicking the <i class="fas fa-users"></i> button. To configure settings such as posting frequency and content warnings, click the <i class="fas fa-cog"></i> button.</p>
|
<p><strong>Important:</strong> To get your bot working, you need to add at least one account for it to learn from. You can do so by clicking the <i class="fas fa-users"></i> button. To configure settings such as posting frequency and content warnings, click the <i class="fas fa-cog"></i> button.</p>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<h2 class="thin centred">Error</h2>
|
<h2 class="thin centred">Error</h2>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<div class='subtle small'>
|
<div class='subtle small'>
|
||||||
<p>FediBooks is beta software. It might behave unexpectedly. You can learn more about FediBooks <a href="/about">here</a>. <br>
|
<p>FediBooks is beta software. It might behave unexpectedly. You can learn more about FediBooks <a href="/about">here</a>. <br>
|
||||||
Website design and FediBooks software by <a href='https://fedi.lynnesbian.space/@LynnearSoftware'>Lynne</a>. This site uses <a href="https://fontawesome.com">Font Awesome</a>. <br>
|
Website design and FediBooks software by <a href='https://fedi.lynnesbian.space/@LynnearSoftware'>Lynne</a>. This site uses <a href="https://fontawesome.com">Font Awesome</a>. <br>
|
||||||
|
Some of FediBooks' functionality requires JavaScript to be enabled, although the core functions such as bot configuration do not. <br>
|
||||||
FediBooks uses a cookie to keep you logged in. Deleting this cookie will log you out, and your bots will still work. You can also sign out <a href="/do/signout">here</a>. <br>
|
FediBooks uses a cookie to keep you logged in. Deleting this cookie will log you out, and your bots will still work. You can also sign out <a href="/do/signout">here</a>. <br>
|
||||||
Source code is available <a href="https://github.com/Lynnesbian/Fedibooks">here</a> under the AGPLv3 license.</p>
|
Source code is available <a href="https://github.com/Lynnesbian/Fedibooks">here</a> under the AGPLv3 license.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link rel="stylesheet" href="https://kit-free.fontawesome.com/releases/latest/css/free.min.css">
|
<link rel="stylesheet" href="https://kit-free.fontawesome.com/releases/latest/css/free.min.css">
|
||||||
<link rel='stylesheet' type='text/css' href="{{ url_for('static', filename='style.css') }}" />
|
<link rel='stylesheet' type='text/css' href="{{ url_for('static', filename='style.css') }}" />
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,700&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,700&display=swap">
|
||||||
|
<script src="{{ url_for('static', filename='script.js') }}"></script>
|
||||||
|
|
31
app/webui.py
31
app/webui.py
|
@ -76,7 +76,7 @@ def render_delete():
|
||||||
# should never happen ;)
|
# should never happen ;)
|
||||||
session['error'] = "An unknown error occurred."
|
session['error'] = "An unknown error occurred."
|
||||||
return redirect(url_for("render_delete"), 303)
|
return redirect(url_for("render_delete"), 303)
|
||||||
|
|
||||||
if bcrypt.checkpw(pw_hashed, data['password']):
|
if bcrypt.checkpw(pw_hashed, data['password']):
|
||||||
# passwords match, delete the account
|
# passwords match, delete the account
|
||||||
session['error'] = "succ ess"
|
session['error'] = "succ ess"
|
||||||
|
@ -106,7 +106,7 @@ def render_delete():
|
||||||
|
|
||||||
c.close()
|
c.close()
|
||||||
mysql.connection.commit()
|
mysql.connection.commit()
|
||||||
|
|
||||||
# TODO: show a "deletion successful" message or something
|
# TODO: show a "deletion successful" message or something
|
||||||
return redirect(url_for("do_signout"), 303)
|
return redirect(url_for("do_signout"), 303)
|
||||||
|
|
||||||
|
@ -159,8 +159,20 @@ def bot_toggle(id):
|
||||||
|
|
||||||
@app.route("/bot/chat/<id>")
|
@app.route("/bot/chat/<id>")
|
||||||
def bot_chat(id):
|
def bot_chat(id):
|
||||||
return render_template("coming_soon.html")
|
# return render_template("coming_soon.html")
|
||||||
# return render_template("/bot/chat.html", bot = id)
|
if bot_check(id):
|
||||||
|
c = mysql.connection.cursor()
|
||||||
|
c.execute("SELECT icon FROM `bots` WHERE handle = %s", (id,))
|
||||||
|
icon = c.fetchone()[0]
|
||||||
|
if icon is None:
|
||||||
|
icon = "/img/bot_generic.png"
|
||||||
|
return render_template("/bot/chat.html", bot = id, icon = icon)
|
||||||
|
|
||||||
|
@app.route("/bot/chat/<id>/message")
|
||||||
|
def bot_chat_message(id):
|
||||||
|
if bot_check(id):
|
||||||
|
_, message = functions.generate_output(id)
|
||||||
|
return message
|
||||||
|
|
||||||
@app.route("/bot/blacklist/<id>")
|
@app.route("/bot/blacklist/<id>")
|
||||||
def bot_blacklist(id):
|
def bot_blacklist(id):
|
||||||
|
@ -258,9 +270,12 @@ def push(id):
|
||||||
'privkey': int(bot[0].rstrip("\0")),
|
'privkey': int(bot[0].rstrip("\0")),
|
||||||
'auth': bot[1]
|
'auth': bot[1]
|
||||||
}
|
}
|
||||||
push_object = client.push_subscription_decrypt_push(request.data, params, request.headers['Encryption'], request.headers['Crypto-Key'])
|
try:
|
||||||
notification = client.notifications(id = push_object['notification_id'])
|
push_object = client.push_subscription_decrypt_push(request.data, params, request.headers['Encryption'], request.headers['Crypto-Key'])
|
||||||
me = client.account_verify_credentials()['id']
|
notification = client.notifications(id = push_object['notification_id'])
|
||||||
|
me = client.account_verify_credentials()['id']
|
||||||
|
except:
|
||||||
|
return "Push failed - do we still have access to {}?".format(id)
|
||||||
|
|
||||||
# first, check how many times the bot has posted in this thread.
|
# first, check how many times the bot has posted in this thread.
|
||||||
# if it's over 15, don't reply.
|
# if it's over 15, don't reply.
|
||||||
|
@ -329,7 +344,7 @@ def do_login():
|
||||||
if data == None:
|
if data == None:
|
||||||
session['error'] = "Incorrect login information."
|
session['error'] = "Incorrect login information."
|
||||||
return redirect(url_for("show_login_page"), 303)
|
return redirect(url_for("show_login_page"), 303)
|
||||||
|
|
||||||
if bcrypt.checkpw(pw_hashed, data['password']):
|
if bcrypt.checkpw(pw_hashed, data['password']):
|
||||||
session['user_id'] = data['id']
|
session['user_id'] = data['id']
|
||||||
return redirect(url_for("render_home"))
|
return redirect(url_for("render_home"))
|
||||||
|
|
Loading…
Reference in a new issue