| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- from flask import Flask, render_template, make_response, request, g
- from bookworm import s3, constants
- import sqlite3
- import json
- import redis
- import os
- import re
- s3client = s3.client()
- app = Flask(__name__)
- r = redis.StrictRedis(host='localhost', port=6379, decode_responses=True)
- def dict_factory(cursor, row):
- d = {}
- for idx, col in enumerate(cursor.description):
- d[col[0]] = row[idx]
- return d
- def get_db():
- db = getattr(g, '_database', None)
- if db is None:
- db = sqlite3.connect('books.db')
- db.row_factory = dict_factory
- g._database = db
- return db
- @app.route('/books/status', methods=['GET'])
- def status_books():
- keys = r.keys(f'{constants.JOB_KEY_PREFIX}*')
- ret = {}
- for key in keys:
- val = r.hgetall(key)
- ret[key] = val
- return json.dumps(ret)
- def clean_book_name(book):
- cbr = re.compile(r'epub|azw3|mobi|\(v[0-9.]+\)')
- return cbr.sub('', book).rstrip('() .-')
- @app.route('/')
- def index():
- objects = s3client.list_objects_v2(Bucket=constants.BUCKET.PROCESSED_FILE)['Contents']
- objects = sorted(objects, key=lambda x: x['LastModified'], reverse=True)
- books = [(obj['Key'], clean_book_name(obj['Key'])) for obj in objects]
- return render_template('kindle-index.j2', books=books)
- @app.route('/book/<path:book>')
- def serve_books(book):
- obj = s3client.get_object(Bucket=constants.BUCKET.PROCESSED_FILE, Key=book)
- data = obj['Body'].read()
- response = make_response(data)
- response.headers.set('Content-Disposition', f'attachment; filename="{book}"')
- response.headers.set('Content-Length', len(data))
- _, ext = os.path.splitext(book)
- if ext == '.mobi':
- content_type = 'application/x-mobipocket-ebook'
- elif ext == '.azw3':
- content_type = 'application/x-mobi8-ebook'
- else:
- content_type = 'text/plain'
- response.headers.set('Content-Type', content_type)
- return response
- @app.route('/book/search', methods=['GET'])
- def search_books():
- terms = request.args.get('terms').split()
- cur = get_db().cursor()
- conditions = []
- for term in terms:
- condition = f"lower(book) like '%{term}%'"
- conditions.append(condition)
- all_conditions = ' AND '.join(conditions)
- rows = cur.execute('SELECT bot, book FROM books where %s LIMIT 100' % all_conditions)
- return json.dumps(list(rows))
- # books = db.fetchall('books',
- # fields=['bot', 'book'],
- # where=('lower(book) like all(%s)', [terms]),
- # limit=100)
- # return json.dumps([b._asdict() for b in books])
- @app.route('/book/fetch', methods=['POST'])
- def fetch_books():
- fetch = request.json
- data = {'command': f'!{fetch["bot"]} {fetch["book"]}',
- 'meta': {
- 'unpack_file_queue': constants.REDIS.Q_UNPACK_FILE,
- 'fetch_file_queue': constants.REDIS.Q_FETCH_FILE,
- 'raw_file_bucket': constants.BUCKET.RAW_FILE,
- 'processed_file_bucket': constants.BUCKET.PROCESSED_FILE,
- }
- }
- r.rpush(constants.REDIS.Q_BOOK_COMMANDS, json.dumps(data))
- return ''
- @app.route('/books/batch_update', methods=['POST'])
- def batch_update():
- fetch = request.json
- if fetch['secret_key'] != 'super_secret':
- return '401'
- batch_update_commands = ['@pondering42', '@dv8', '@shytot', '@dragnbreaker', '@Xon-new']
- for command in batch_update_commands:
- data = {'command': command,
- 'meta': {
- 'unpack_file_queue': constants.REDIS.Q_PROCESS_BATCH_FILE,
- 'fetch_file_queue': constants.REDIS.Q_FETCH_FILE,
- 'raw_file_bucket': constants.BUCKET.RAW_FILE,
- 'processed_file_bucket': constants.BUCKET.PROCESSED_FILE,
- }
- }
- r.rpush(constants.REDIS.Q_BOOK_COMMANDS, json.dumps(data))
- return ''
- def main():
- db = sqlite3.connect('books.db')
- c = db.cursor()
- sql = 'CREATE TABLE IF NOT EXISTS books (bot TEXT(40), book TEXT(200), size INT)'
- c.execute(sql)
- sql = 'CREATE UNIQUE INDEX IF NOT EXISTS books_unique ON books(bot, book)'
- c.execute(sql)
- db.commit()
- db.close()
- app.run(host='0.0.0.0', debug=True)
- if __name__ == '__main__':
- main()
|