mirror of
https://github.com/Lynnesbian/FediBooks/
synced 2024-11-25 16:48:58 +00:00
Compare commits
No commits in common. "a981c7a171eff2126fd421716beba72696633db4" and "38463fefb2aec3a1cd59f7e9efdd598296205573" have entirely different histories.
a981c7a171
...
38463fefb2
5 changed files with 15 additions and 85 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,3 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
config.json
|
config.json
|
||||||
planning.txt
|
planning.txt
|
||||||
*.pyc
|
|
||||||
|
|
36
functions.py
36
functions.py
|
@ -34,13 +34,8 @@ 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 make_post(handle):
|
||||||
id = None
|
handle = handle[0]
|
||||||
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'],
|
||||||
|
@ -52,8 +47,7 @@ def make_post(args):
|
||||||
c = db.cursor()
|
c = db.cursor()
|
||||||
dc.execute("""
|
dc.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
learn_from_cw,
|
learn_from_cw,
|
||||||
length,
|
|
||||||
fake_mentions,
|
fake_mentions,
|
||||||
fake_mentions_full,
|
fake_mentions_full,
|
||||||
post_privacy,
|
post_privacy,
|
||||||
|
@ -95,22 +89,19 @@ def make_post(args):
|
||||||
# 3. convert the tuple to a list
|
# 3. convert the tuple to a list
|
||||||
# 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:
|
|
||||||
print("No posts to learn from.")
|
|
||||||
return
|
|
||||||
|
|
||||||
model = nlt_fixed(posts)
|
model = nlt_fixed(posts)
|
||||||
tries = 0
|
tries = 0
|
||||||
post = None
|
post = None
|
||||||
|
# even with such a high tries value for markovify, it still sometimes returns none.
|
||||||
|
# so we implement our own tries function as well, and try ten times.
|
||||||
|
|
||||||
if bot['fake_mentions'] == 'never':
|
if bot['fake_mentions'] == 'never':
|
||||||
# remove all mentions from the training data before the markov model sees it
|
# remove all mentions from the training data before the markov model sees it
|
||||||
posts = re.sub(r"@(\w+)@([\w.]+)\s?", "", posts)
|
posts = re.sub(r"@(\w+)@([\w.]+)\s?", "", posts)
|
||||||
|
|
||||||
# even with such a high tries value for markovify, it still sometimes returns none.
|
|
||||||
# so we implement our own tries function as well, and try ten times.
|
|
||||||
while post is None and tries < 10:
|
while post is None and tries < 10:
|
||||||
post = model.make_short_sentence(bot['length'], tries = 1000)
|
post = model.make_short_sentence(500, tries = 10000)
|
||||||
tries += 1
|
tries += 1
|
||||||
|
|
||||||
if post == None:
|
if post == None:
|
||||||
|
@ -131,16 +122,7 @@ def make_post(args):
|
||||||
post = re.sub(r"@(\w+)@([\w.]+)", r"@{}\1".format(zws), post)
|
post = re.sub(r"@(\w+)@([\w.]+)", r"@{}\1".format(zws), post)
|
||||||
|
|
||||||
print(post)
|
print(post)
|
||||||
visibility = bot['post_privacy'] if len(args) == 1 else args[2]
|
client.status_post(post, visibility = bot['post_privacy'], spoiler_text = bot['content_warning'])
|
||||||
if acct is not None:
|
|
||||||
post = "{} {}".format(acct, post)
|
|
||||||
|
|
||||||
# ensure post isn't longer than bot['length']
|
c.execute("UPDATE bots SET last_post = CURRENT_TIMESTAMP() WHERE handle = %s", (handle,))
|
||||||
post = post[:bot['length']]
|
db.commit()
|
||||||
# send toot!!
|
|
||||||
client.status_post(post, id, visibility = visibility, spoiler_text = bot['content_warning'])
|
|
||||||
|
|
||||||
if id == None:
|
|
||||||
# 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,))
|
|
||||||
db.commit()
|
|
||||||
|
|
|
@ -13,8 +13,7 @@ def scrape_posts(account):
|
||||||
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,))
|
||||||
count = c.fetchone()
|
if c.fetchone()[0] > 0:
|
||||||
if count is not None and count[0] > 0:
|
|
||||||
# we've downloaded this user's posts before
|
# we've downloaded this user's posts before
|
||||||
# find out the most recently downloaded post of theirs
|
# find out the most recently downloaded post of theirs
|
||||||
c.execute("SELECT `post_id` FROM `posts` WHERE `fedi_id` = %s ORDER BY `id` DESC LIMIT 1", (handle,))
|
c.execute("SELECT `post_id` FROM `posts` WHERE `fedi_id` = %s ORDER BY `id` DESC LIMIT 1", (handle,))
|
||||||
|
@ -79,9 +78,8 @@ def scrape_posts(account):
|
||||||
else:
|
else:
|
||||||
j = r.json()
|
j = r.json()
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
c.close()
|
c.close()
|
||||||
print("Finished scraping {}".format(handle))
|
|
||||||
|
|
||||||
print("Establishing DB connection")
|
print("Establishing DB connection")
|
||||||
db = MySQLdb.connect(
|
db = MySQLdb.connect(
|
||||||
|
@ -101,6 +99,4 @@ accounts = cursor.fetchall()
|
||||||
with Pool(cfg['service_threads']) as p:
|
with Pool(cfg['service_threads']) as p:
|
||||||
p.map(scrape_posts, accounts)
|
p.map(scrape_posts, accounts)
|
||||||
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
print("Done!")
|
print("Done!")
|
||||||
|
|
|
@ -20,7 +20,6 @@ print("Cleaning up database")
|
||||||
# delete any fedi accounts we no longer need
|
# delete any fedi accounts we no longer need
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("DELETE FROM fedi_accounts WHERE handle NOT IN (SELECT fedi_id FROM bot_learned_accounts)")
|
cursor.execute("DELETE FROM fedi_accounts WHERE handle NOT IN (SELECT fedi_id FROM bot_learned_accounts)")
|
||||||
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")
|
||||||
|
@ -30,5 +29,3 @@ with Pool(cfg['service_threads']) as p:
|
||||||
p.map(functions.make_post, bots)
|
p.map(functions.make_post, bots)
|
||||||
|
|
||||||
#TODO: other cron tasks should be done here, like updating profile pictures
|
#TODO: other cron tasks should be done here, like updating profile pictures
|
||||||
|
|
||||||
db.commit()
|
|
||||||
|
|
52
webui.py
52
webui.py
|
@ -5,7 +5,6 @@ import requests
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
import bcrypt
|
import bcrypt
|
||||||
import json, hashlib, re
|
import json, hashlib, re
|
||||||
import functions
|
|
||||||
|
|
||||||
cfg = json.load(open("config.json"))
|
cfg = json.load(open("config.json"))
|
||||||
|
|
||||||
|
@ -23,7 +22,7 @@ scopes = ['write:statuses', 'write:accounts', 'read:accounts', 'read:notificatio
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def login_check():
|
def login_check():
|
||||||
if request.path not in ['/', '/about', '/welcome', '/login', '/signup', '/do/login', '/do/signup', '/static/style.css'] and not request.path.startswith("/push"):
|
if request.path not in ['/', '/about', '/welcome', '/login', '/signup', '/do/login', '/do/signup', '/static/style.css']:
|
||||||
# page requires authentication
|
# page requires authentication
|
||||||
if 'user_id' not in session:
|
if 'user_id' not in session:
|
||||||
return redirect(url_for('home'))
|
return redirect(url_for('home'))
|
||||||
|
@ -490,52 +489,6 @@ def do_authenticate_bot():
|
||||||
session['step'] = 4
|
session['step'] = 4
|
||||||
return redirect(url_for("bot_create"), 303)
|
return redirect(url_for("bot_create"), 303)
|
||||||
|
|
||||||
@app.route("/push/<id>", methods = ['POST'])
|
|
||||||
def push(id):
|
|
||||||
c = mysql.connection.cursor()
|
|
||||||
c.execute("SELECT client_id, client_secret, secret FROM credentials WHERE id = (SELECT credentials_id FROM bots WHERE handle = %s)", (id,))
|
|
||||||
login = c.fetchone()
|
|
||||||
client = Mastodon(
|
|
||||||
client_id = login[0],
|
|
||||||
client_secret = login[1],
|
|
||||||
access_token = login[2],
|
|
||||||
api_base_url = "https://{}".format(id.split("@")[2])
|
|
||||||
)
|
|
||||||
|
|
||||||
c.execute("SELECT push_private_key, push_secret, replies_enabled FROM bots WHERE handle = %s", (id,))
|
|
||||||
bot = c.fetchone()
|
|
||||||
if not bot[2]:
|
|
||||||
return "Replies disabled."
|
|
||||||
|
|
||||||
params = {
|
|
||||||
'privkey': int(bot[0].rstrip("\0")),
|
|
||||||
'auth': bot[1]
|
|
||||||
}
|
|
||||||
push_object = client.push_subscription_decrypt_push(request.data, params, request.headers['Encryption'], request.headers['Crypto-Key'])
|
|
||||||
notification = client.notifications(id = push_object['notification_id'])
|
|
||||||
me = client.account_verify_credentials()['id']
|
|
||||||
|
|
||||||
# first, check how many times the bot has posted in this thread.
|
|
||||||
# if it's over 15, don't reply.
|
|
||||||
# this is to stop endless reply chains between two bots.
|
|
||||||
try:
|
|
||||||
context = client.status_context(notification['status']['id'])
|
|
||||||
my_posts = 0
|
|
||||||
for post in context['ancestors']:
|
|
||||||
if post['account']['id'] == me:
|
|
||||||
my_posts += 1
|
|
||||||
if my_posts >= 15:
|
|
||||||
# don't reply
|
|
||||||
return "Didn't reply."
|
|
||||||
except:
|
|
||||||
# failed to fetch context
|
|
||||||
# assume we haven't been participating in this thread
|
|
||||||
pass
|
|
||||||
|
|
||||||
functions.make_post([id, notification['status']['id'], notification['status']['visibility'], "@" + notification['account']['acct']])
|
|
||||||
|
|
||||||
return "Success!"
|
|
||||||
|
|
||||||
@app.route("/do/signup", methods=['POST'])
|
@app.route("/do/signup", methods=['POST'])
|
||||||
def do_signup():
|
def do_signup():
|
||||||
# email validation is basically impossible without actually sending an email to the address
|
# email validation is basically impossible without actually sending an email to the address
|
||||||
|
@ -601,6 +554,9 @@ def img_bot_generic():
|
||||||
|
|
||||||
@app.route("/favicon.ico")
|
@app.route("/favicon.ico")
|
||||||
def favicon():
|
def favicon():
|
||||||
|
# so there's a weird bug where one of my firefox installs wants the favicon, and when it can't find it, it requests /
|
||||||
|
# requesting / resets your session['step'] to 1, which breaks all the multi-step things.
|
||||||
|
# so we need to give it a favicon.
|
||||||
return send_file("static/favicon.ico")
|
return send_file("static/favicon.ico")
|
||||||
|
|
||||||
def bot_check(bot):
|
def bot_check(bot):
|
||||||
|
|
Loading…
Reference in a new issue