Compare commits
146 Commits
our-style
...
master-of-
Author | SHA1 | Date | |
---|---|---|---|
01b3b0022f | |||
|
315e6f8142 | ||
|
17fc89ebbd | ||
|
fbb586b56c | ||
|
f9bbd5e6af | ||
|
412b26244a | ||
|
32f1d87831 | ||
|
216d60c84d | ||
|
ad6feb7afb | ||
|
a95d556e8c | ||
|
956b59c2fa | ||
|
a325ea91fe | ||
|
a84da0a6f9 | ||
|
9838f7f024 | ||
|
d21e5e0bf6 | ||
|
38842ec947 | ||
|
5ad7f7514d | ||
|
365c4909fe | ||
|
71f72c66f3 | ||
|
d4e585fb13 | ||
|
92bb87c816 | ||
|
9e90bd2458 | ||
|
2b5fd02929 | ||
|
d4131c26c8 | ||
|
edd102e5e3 | ||
|
2a5a3fd8e4 | ||
|
a7e17694c2 | ||
|
d0163a8963 | ||
|
e83dfebee5 | ||
|
c8241f2613 | ||
|
25e5430b4c | ||
|
e34be51a16 | ||
|
e30077bf4d | ||
|
3320baf0f2 | ||
|
68e455fe7b | ||
|
134297911b | ||
|
d89ba3f582 | ||
|
14057ead4d | ||
|
1b2bfb601b | ||
|
b3d20faec3 | ||
|
2a68a6d8c2 | ||
|
c36968ec16 | ||
|
e6ae7440aa | ||
|
3f3e5711b6 | ||
|
a416e46139 | ||
|
33c609645c | ||
|
1f58b37b96 | ||
|
1ff5f2803f | ||
|
e91c6dba41 | ||
|
5c99fc6f8d | ||
|
bb6f126811 | ||
|
0e727ef4fe | ||
|
cf479d2353 | ||
|
9aaec391b2 | ||
|
7600ab6e3e | ||
|
fd4ff11562 | ||
|
bceda9bdde | ||
|
ef157ed64b | ||
|
90522346ac | ||
|
d5f4fd3989 | ||
|
765bad6d5e | ||
|
348cd21ed9 | ||
|
5995344e04 | ||
|
6b3ae65d73 | ||
|
b3dc40fa20 | ||
|
03c197aa6f | ||
|
6b2b0a6142 | ||
|
b858c9db9d | ||
|
f37c6aeecd | ||
|
d2907b9362 | ||
|
85dce5ce2e | ||
|
f482dd03ed | ||
|
75958f9d9a | ||
|
8415845488 | ||
|
5790ea301c | ||
|
7a08ae00cd | ||
|
d646b120d5 | ||
|
2f630ddde0 | ||
|
25a99b4549 | ||
|
5938f4e063 | ||
|
8d98c04fa3 | ||
|
67fac37e44 | ||
|
a46cc7c78c | ||
|
ae638c25db | ||
|
a08e14367b | ||
|
75f2d5a08f | ||
|
0b9f373486 | ||
|
24f294bad1 | ||
|
48ec4c9c59 | ||
|
496ca85240 | ||
|
69442b671e | ||
|
05370dae8b | ||
|
694e1dbfcd | ||
|
fe439b6b1a | ||
|
7dce872df3 | ||
|
88e2b021f9 | ||
|
ce5f33e604 | ||
|
57e598814f | ||
|
f49f97a8ea | ||
|
390974f1a3 | ||
|
089b022a3b | ||
|
c30e2c8705 | ||
|
b391326806 | ||
|
fc5b0d7491 | ||
|
d97035a32b | ||
|
a622768a13 | ||
|
78a60c6d90 | ||
|
7f94bade46 | ||
|
586b76bc25 | ||
|
6f37ff03ab | ||
|
b7f4813ec0 | ||
|
e7fee4999e | ||
|
1e2d39a5c0 | ||
|
feec65123a | ||
|
a807114c58 | ||
|
ed2cf28893 | ||
|
622fa4f50d | ||
|
ca15046bda | ||
|
e96ff651cc | ||
|
f653d1f234 | ||
|
ee869d4693 | ||
|
621dadd47d | ||
|
03be9453fb | ||
|
39e16ffdb8 | ||
|
919c860475 | ||
|
54bb686249 | ||
|
22e2062cb1 | ||
|
27be10ee32 | ||
|
c26c016adc | ||
|
a4ea21dfa6 | ||
|
ed851efd50 | ||
|
410861aa75 | ||
|
5b25dced59 | ||
|
75e07c2118 | ||
|
113bd64b0e | ||
|
6e9587e074 | ||
|
421fecce4d | ||
|
c5a4c8e6ed | ||
|
9727bf5c61 | ||
|
94524a326d | ||
|
e5c4ec6730 | ||
|
6414aa4410 | ||
|
411a973102 | ||
|
ec8a36b7ed | ||
|
8b54e30493 | ||
|
353551b219 |
89
.drone.yml
89
.drone.yml
@ -15,54 +15,93 @@ steps:
|
|||||||
- name: pull into the folduh
|
- name: pull into the folduh
|
||||||
commands:
|
commands:
|
||||||
- cd /usr/share/repos/$DRONE_REPO_NAME
|
- cd /usr/share/repos/$DRONE_REPO_NAME
|
||||||
|
- git checkout $DRONE_COMMIT_BRANCH
|
||||||
- git pull origin $DRONE_COMMIT_BRANCH
|
- git pull origin $DRONE_COMMIT_BRANCH
|
||||||
- name: build
|
# - name: build
|
||||||
environment:
|
# environment:
|
||||||
DOCKER_TLS_VERIFY: 1
|
# DOCKER_TLS_VERIFY: 1
|
||||||
DOCKER_HOST: "tcp://192.168.49.2:2376"
|
# DOCKER_HOST: "tcp://192.168.49.2:2376"
|
||||||
DOCKER_CERT_PATH: "/home/hogweed1/.minikube/certs"
|
# DOCKER_CERT_PATH: "/home/hogweed1/.minikube/certs"
|
||||||
MINIKUBE_ACTIVE_DOCKERD: "minikube"
|
# MINIKUBE_ACTIVE_DOCKERD: "minikube"
|
||||||
|
# commands:
|
||||||
|
# - cd /usr/share/repos/$DRONE_REPO_NAME
|
||||||
|
# - git checkout $DRONE_COMMIT_BRANCH
|
||||||
|
# - docker build . -t ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)"
|
||||||
|
# - docker tag ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)" ${DRONE_REPO_NAME}:latest
|
||||||
|
# - docker tag ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)" ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}
|
||||||
|
- name: build to harbor
|
||||||
commands:
|
commands:
|
||||||
- cd /usr/share/repos/$DRONE_REPO_NAME
|
- cd /usr/share/repos/$DRONE_REPO_NAME
|
||||||
- git checkout $DRONE_COMMIT_BRANCH
|
- git checkout $DRONE_COMMIT_BRANCH
|
||||||
- docker build . -t ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)"
|
#- docker build . -t ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)"
|
||||||
- docker tag ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)" ${DRONE_REPO_NAME}:latest
|
#- docker tag ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)" harbor.guaranteedstruggle.host/library/${DRONE_REPO_NAME}:latest
|
||||||
- docker tag ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)" ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}
|
#- docker tag ${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-"$(git rev-parse --short HEAD)" harbor.guaranteedstruggle.host/library/${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}
|
||||||
|
- docker build . -t harbor.guaranteedstruggle.host/library/${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}
|
||||||
|
- docker login harbor.guaranteedstruggle.host -u 'robot$drono' -p valgBwMgcB86azvmuezTOC3omjXZ1NZe
|
||||||
|
- docker push harbor.guaranteedstruggle.host/library/${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}
|
||||||
|
|
||||||
|
|
||||||
- name: restart deployment master
|
- name: restart deployment master
|
||||||
environment:
|
environment:
|
||||||
DOCKER_TLS_VERIFY: 1
|
KUBECONFIG: /etc/kubernetes/admin.conf
|
||||||
DOCKER_HOST: "tcp://192.168.49.2:2376"
|
|
||||||
DOCKER_CERT_PATH: "/home/hogweed1/.minikube/certs"
|
|
||||||
MINIKUBE_ACTIVE_DOCKERD: "minikube"
|
|
||||||
commands:
|
commands:
|
||||||
- su - hogweed1 -c "minikube kubectl -- rollout restart -n vdk2ch deployment flask-htmx-master"
|
- kubectl rollout restart -n vdk2ch deployment flask-htmx-master
|
||||||
when:
|
when:
|
||||||
branch:
|
branch:
|
||||||
- master-of-slaves
|
- master-of-slaves
|
||||||
|
|
||||||
- name: restart deployment dev
|
- name: restart deployment dev
|
||||||
environment:
|
environment:
|
||||||
DOCKER_TLS_VERIFY: 1
|
KUBECONFIG: /etc/kubernetes/admin.conf
|
||||||
DOCKER_HOST: "tcp://192.168.49.2:2376"
|
|
||||||
DOCKER_CERT_PATH: "/home/hogweed1/.minikube/certs"
|
|
||||||
MINIKUBE_ACTIVE_DOCKERD: "minikube"
|
|
||||||
commands:
|
commands:
|
||||||
- su - hogweed1 -c "minikube kubectl -- rollout restart -n vdk2ch deployment flask-htmx-dev"
|
- kubectl rollout restart -n vdk2ch deployment flask-htmx-dev
|
||||||
when:
|
when:
|
||||||
branch:
|
branch:
|
||||||
- dev
|
- dev
|
||||||
|
|
||||||
- name: restart deployment our-style
|
- name: restart deployment our-style
|
||||||
environment:
|
environment:
|
||||||
DOCKER_TLS_VERIFY: 1
|
KUBECONFIG: /etc/kubernetes/admin.conf
|
||||||
DOCKER_HOST: "tcp://192.168.49.2:2376"
|
|
||||||
DOCKER_CERT_PATH: "/home/hogweed1/.minikube/certs"
|
|
||||||
MINIKUBE_ACTIVE_DOCKERD: "minikube"
|
|
||||||
commands:
|
commands:
|
||||||
- su - hogweed1 -c "minikube kubectl -- rollout restart -n vdk2ch deployment flask-htmx-our-style"
|
- kubectl rollout restart -n vdk2ch deployment flask-htmx-our-style
|
||||||
when:
|
when:
|
||||||
branch:
|
branch:
|
||||||
- our-style
|
- our-style
|
||||||
|
|
||||||
|
# - name: restart deployment master
|
||||||
|
# environment:
|
||||||
|
# DOCKER_TLS_VERIFY: 1
|
||||||
|
# DOCKER_HOST: "tcp://192.168.49.2:2376"
|
||||||
|
# DOCKER_CERT_PATH: "/home/hogweed1/.minikube/certs"
|
||||||
|
# MINIKUBE_ACTIVE_DOCKERD: "minikube"
|
||||||
|
# commands:
|
||||||
|
# - su - hogweed1 -c "minikube kubectl -- rollout restart -n vdk2ch deployment flask-htmx-master"
|
||||||
|
# when:
|
||||||
|
# branch:
|
||||||
|
# - master-of-slaves
|
||||||
|
|
||||||
|
# - name: restart deployment dev
|
||||||
|
# environment:
|
||||||
|
# DOCKER_TLS_VERIFY: 1
|
||||||
|
# DOCKER_HOST: "tcp://192.168.49.2:2376"
|
||||||
|
# DOCKER_CERT_PATH: "/home/hogweed1/.minikube/certs"
|
||||||
|
# MINIKUBE_ACTIVE_DOCKERD: "minikube"
|
||||||
|
# commands:
|
||||||
|
# - su - hogweed1 -c "minikube kubectl -- rollout restart -n vdk2ch deployment flask-htmx-dev"
|
||||||
|
# when:
|
||||||
|
# branch:
|
||||||
|
# - dev
|
||||||
|
|
||||||
|
# - name: restart deployment our-style
|
||||||
|
# environment:
|
||||||
|
# DOCKER_TLS_VERIFY: 1
|
||||||
|
# DOCKER_HOST: "tcp://192.168.49.2:2376"
|
||||||
|
# DOCKER_CERT_PATH: "/home/hogweed1/.minikube/certs"
|
||||||
|
# MINIKUBE_ACTIVE_DOCKERD: "minikube"
|
||||||
|
# commands:
|
||||||
|
# - su - hogweed1 -c "minikube kubectl -- rollout restart -n vdk2ch deployment flask-htmx-our-style"
|
||||||
|
# when:
|
||||||
|
# branch:
|
||||||
|
# - our-style
|
||||||
|
|
||||||
|
|
@ -212,4 +212,5 @@ stateDiagram-v2
|
|||||||
Grafana --> dash_join
|
Grafana --> dash_join
|
||||||
dash_join --> User : дашборды
|
dash_join --> User : дашборды
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
286
app.py
286
app.py
@ -1,12 +1,13 @@
|
|||||||
from flask import Flask, render_template, request
|
from flask import Flask, render_template, request, jsonify, make_response
|
||||||
from flask_assets import Bundle, Environment
|
|
||||||
from todo import todos
|
from flask_assets import Bundle, Environment
|
||||||
#from boards import board_list
|
from arango import ArangoClient
|
||||||
from threads import threads_lists
|
from minio import Minio
|
||||||
from threads_with_posts import open_threads
|
|
||||||
from arango import ArangoClient
|
import socket, os
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import socket
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@ -14,23 +15,32 @@ assets = Environment(app)
|
|||||||
css = Bundle("src/*.css", output="dist/main.css")
|
css = Bundle("src/*.css", output="dist/main.css")
|
||||||
|
|
||||||
# https://unpkg.com/htmx.org
|
# https://unpkg.com/htmx.org
|
||||||
js = Bundle("src/*.js", output="dist/main.js")
|
#js = Bundle("src/*.js", output="dist/main.js")
|
||||||
|
|
||||||
assets.register("css", css)
|
assets.register("css", css)
|
||||||
assets.register("js", js)
|
#assets.register("js", js)
|
||||||
css.build()
|
css.build()
|
||||||
js.build()
|
#js.build()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
docker_short_id = socket.gethostname()
|
docker_short_id = socket.gethostname()
|
||||||
|
|
||||||
arango_client = ArangoClient(hosts='https://arango.vdk2ch.ru')
|
arango_client = ArangoClient(hosts='https://arango.guaranteedstruggle.host')
|
||||||
db = arango_client.db('board1', username='root', password='stolendick527')
|
db = arango_client.db('board1', username='root', password='123-very-unsafe-way-to-protect-yourself321')
|
||||||
|
|
||||||
|
|
||||||
# предполагается что меняться список будет весьма редко, поэтому подхватываем при лишь при перезапуске
|
# предполагается что меняться список будет весьма редко, поэтому подхватываем при лишь при перезапуске
|
||||||
boards0 = db.collection('boards')
|
# # boards0 = db.collection('boards')
|
||||||
board_list = [ k['_key'] for k in boards0]
|
# # print(boards0)
|
||||||
|
# # board_list = [ k['_key'] for k in boards0]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/get_my_ip")
|
||||||
|
def get_my_ip():
|
||||||
|
return jsonify({'ip': request.remote_addr,
|
||||||
|
'real-ip': request.environ.get('HTTP_X_REAL_IP', request.remote_addr)}), 200
|
||||||
|
|
||||||
|
|
||||||
@app.route('/liveness')
|
@app.route('/liveness')
|
||||||
@ -39,55 +49,194 @@ def healthx():
|
|||||||
|
|
||||||
@app.route('/readiness')
|
@app.route('/readiness')
|
||||||
def healthz():
|
def healthz():
|
||||||
|
#### TODU return arango check
|
||||||
|
|
||||||
return "<h1><center>Readiness check completed</center><h1>"
|
return "<h1><center>Readiness check completed</center><h1>"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def homepage():
|
def homepage():
|
||||||
|
boards0 = db.collection('boards')
|
||||||
|
board_list = [ k['_key'] for k in boards0]
|
||||||
return render_template("main-page.html", host_id=docker_short_id, boards=board_list)
|
return render_template("main-page.html", host_id=docker_short_id, boards=board_list)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/boards/<board_id>")
|
|
||||||
def page_board(board_id):
|
|
||||||
|
|
||||||
b_threads = [ open_threads[thread_id] for thread_id in open_threads if thread_id in threads_lists[board_id]]
|
#### TODO если борды нет, то возвращать 404 мемную
|
||||||
return render_template("board.html", host_id=docker_short_id, board_id=board_id, boards=board_list, board_threads=b_threads)
|
#### TODO если треда нет, то возвращать 404 мемную
|
||||||
|
|
||||||
|
|
||||||
|
#### DONE route :: /{board}/
|
||||||
@app.route("/db_posts")
|
@app.route('/<board>')
|
||||||
def page_posts_from_db():
|
def board_posts(board=None):
|
||||||
|
|
||||||
postos = db.collection('posts')
|
postos = db.collection('posts')
|
||||||
postos = [ p for p in postos]
|
postos = [ p for p in postos if p.get('root_post') == True and p.get('board') == board ]
|
||||||
postos = sorted(postos, key=lambda posto: posto['_key'], reverse=False)
|
postos = sorted(postos, key=lambda posto: int(posto['_key']), reverse=False)
|
||||||
|
|
||||||
return render_template("interactive-posts.html", host_id=docker_short_id, postos=postos)
|
boards0 = db.collection('boards')
|
||||||
|
board_list = [ k['_key'] for k in boards0]
|
||||||
|
return render_template("board-posts.html", host_id=docker_short_id, postos=postos, board=board, target_post_id=None, boards=board_list)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/post_my_post/<post_key>', methods=['POST'])
|
#### TODO route :: /{board}/{thread}/
|
||||||
def post_a_post(post_key):
|
#### TODO убрать отсюда чужие рут-потсы
|
||||||
|
@app.route("/<board>/<int:target_post_id>")
|
||||||
|
def thread_posts(board=None, target_post_id=None):
|
||||||
|
|
||||||
|
## взять рут-пост
|
||||||
|
## взять всех его детей
|
||||||
|
|
||||||
|
# postos = db.collection('posts')
|
||||||
|
# postos = [ p for p in postos]
|
||||||
|
# postos = sorted(postos, key=lambda posto: int(posto['_key']), reverse=False)
|
||||||
|
|
||||||
|
cursor = db.aql.execute(
|
||||||
|
f"""FOR ppp IN posts
|
||||||
|
FILTER ppp.root_post == True and ppp._key == "{target_post_id}"
|
||||||
|
FOR v IN 1..9999 OUTBOUND ppp post_parents RETURN v"""
|
||||||
|
)
|
||||||
|
|
||||||
|
postos = [ ]
|
||||||
|
while not cursor.empty(): # Pop until nothing is left on the cursor.
|
||||||
|
postos.append(cursor.pop())
|
||||||
|
cursor = db.aql.execute(
|
||||||
|
f'RETURN DOCUMENT("posts/{target_post_id}")'
|
||||||
|
)
|
||||||
|
while not cursor.empty(): # Pop until nothing is left on the cursor.
|
||||||
|
postos.append(cursor.pop())
|
||||||
|
postos = [ p for p in postos ]
|
||||||
|
postos = sorted(postos, key=lambda posto: int(posto['_key']), reverse=False)
|
||||||
|
|
||||||
|
if not target_post_id:
|
||||||
|
target_post_id = postos[0]['_key']
|
||||||
|
|
||||||
|
|
||||||
|
boards0 = db.collection('boards')
|
||||||
|
board_list = [ k['_key'] for k in boards0]
|
||||||
|
return render_template("interactive-posts.html", board=board, host_id=docker_short_id, postos=postos, target_post_id=target_post_id, boards=board_list)
|
||||||
|
|
||||||
|
|
||||||
|
#### TODO route :: /{board}/create_thread/{target_post_id}
|
||||||
|
@app.route("/<board>/create-thread/<target_post_id>", methods=['POST'])
|
||||||
|
def create_thread(board=None, target_post_id=None):
|
||||||
|
|
||||||
postos = db.collection('posts')
|
postos = db.collection('posts')
|
||||||
|
data = request.form['send_this_text']
|
||||||
|
|
||||||
#### TODO проверить как-то по-умному что мы таки его добавили
|
|
||||||
metadata = postos.insert({
|
metadata = postos.insert({
|
||||||
'texto': 'next post is this',
|
'texto': data,
|
||||||
'parent_post': f'{post_key}'
|
"root_post": True,
|
||||||
|
'board': board,
|
||||||
|
'images': [],
|
||||||
|
"children_num": 0,
|
||||||
|
"answers_num": 0,
|
||||||
|
"answers_list": [ [], [], [] ]
|
||||||
|
}, overwrite_mode='update')
|
||||||
|
|
||||||
|
response = make_response()
|
||||||
|
response.headers["HX-Redirect"] = f"/{board}/{metadata['_key']}"
|
||||||
|
response.status_code = 200
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
#### TODO route :: /{board}/{thread}/answer_post/
|
||||||
|
|
||||||
|
#### TODO route :: /{board}/{thread}/post_to_another_post/
|
||||||
|
|
||||||
|
|
||||||
|
# @app.route('/db_posts')
|
||||||
|
# @app.route("/db_posts/<target_post_id>")
|
||||||
|
# def page_posts_from_db(target_post_id=None):
|
||||||
|
|
||||||
|
# postos = db.collection('posts')
|
||||||
|
# postos = [ p for p in postos]
|
||||||
|
# postos = sorted(postos, key=lambda posto: int(posto['_key']), reverse=False)
|
||||||
|
|
||||||
|
|
||||||
|
# for p in postos:
|
||||||
|
# #if p['root_post']:
|
||||||
|
# print(p)
|
||||||
|
|
||||||
|
# if not target_post_id:
|
||||||
|
# target_post_id = postos[0]['_key']
|
||||||
|
|
||||||
|
# return render_template("interactive-posts.html", host_id=docker_short_id, postos=postos, target_post_id=target_post_id)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/<board>/answer_post/<target_post_id>", methods=['POST'])
|
||||||
|
def answer_post(board, target_post_id):
|
||||||
|
|
||||||
|
postos = db.collection('posts')
|
||||||
|
postos = [ p for p in postos ]
|
||||||
|
postos = sorted(postos, key=lambda posto: int(posto['_key']), reverse=False)
|
||||||
|
|
||||||
|
## ?? wut
|
||||||
|
if not target_post_id:
|
||||||
|
target_post_id = postos[0]['_key']
|
||||||
|
|
||||||
|
return render_template("answer-post.html", board=board, target_post_id=target_post_id)
|
||||||
|
|
||||||
|
|
||||||
|
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'mp4', 'webm', 'webp'}
|
||||||
|
def allowed_file(filename):
|
||||||
|
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
||||||
|
|
||||||
|
@app.route('/<board>/post_to_another_post/<post_key>', methods=['POST'])
|
||||||
|
def post_to_post(board, post_key):
|
||||||
|
|
||||||
|
|
||||||
|
#### TODO resize pics https://stackoverflow.com/questions/53337318/how-can-i-resize-image-with-pil-on-upload-and-serve-them-with-flask-cloudy
|
||||||
|
#### TODO allow only imgs, videos, and gifs
|
||||||
|
if 'file' in request.files:
|
||||||
|
|
||||||
|
minioClient = Minio( "static.guaranteedstruggle.host" )
|
||||||
|
bucket_name = "thread-pics"
|
||||||
|
|
||||||
|
files = request.files.getlist("file")
|
||||||
|
for file in files:
|
||||||
|
size = os.fstat(file.fileno()).st_size
|
||||||
|
#### работает ли??
|
||||||
|
if allowed_file(file.filename):
|
||||||
|
minioClient.put_object(
|
||||||
|
bucket_name, file.filename, file, size
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(f'somebody tried to put this inside minio: {file.filename} size: {size}')
|
||||||
|
|
||||||
|
|
||||||
|
postos = db.collection('posts')
|
||||||
|
data = request.form['send_this_text']
|
||||||
|
|
||||||
|
|
||||||
|
cursor = db.aql.execute(
|
||||||
|
f'RETURN DOCUMENT("posts/{post_key}")'
|
||||||
|
)
|
||||||
|
p = cursor.pop()
|
||||||
|
|
||||||
|
if p.get('root_post') == True:
|
||||||
|
thread = p.get('_key')
|
||||||
|
elif not p.get('root_post'):
|
||||||
|
thread = p.get('thread')
|
||||||
|
else:
|
||||||
|
thread = 'ERROR'
|
||||||
|
|
||||||
|
print(p)
|
||||||
|
metadata = postos.insert({
|
||||||
|
'texto': data,
|
||||||
|
'parent_post': f'{post_key}',
|
||||||
|
'images': [],
|
||||||
|
"thread": thread
|
||||||
}, overwrite_mode='update')
|
}, overwrite_mode='update')
|
||||||
|
|
||||||
metadata = db.collection('post_parents').insert({
|
metadata = db.collection('post_parents').insert({
|
||||||
# '_key': post_key,
|
|
||||||
'_from': f'posts/{post_key}',
|
'_from': f'posts/{post_key}',
|
||||||
'_to': f'posts/{metadata["_key"]}'
|
'_to': f'posts/{metadata["_key"]}'
|
||||||
}, overwrite_mode='update')
|
}, overwrite_mode='update')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### TODO оптимайз для только тредовых штук
|
||||||
cursor = db.aql.execute(
|
cursor = db.aql.execute(
|
||||||
"""FOR ppp IN posts
|
"""FOR ppp IN posts
|
||||||
LET children = (FOR v IN 1..9999 OUTBOUND ppp post_parents RETURN v)
|
LET children = (FOR v IN 1..9999 OUTBOUND ppp post_parents RETURN v)
|
||||||
@ -95,41 +244,36 @@ def post_a_post(post_key):
|
|||||||
)
|
)
|
||||||
cursor = db.aql.execute(
|
cursor = db.aql.execute(
|
||||||
"""FOR ppp IN posts
|
"""FOR ppp IN posts
|
||||||
LET children = (FOR v IN 1OUTBOUND ppp post_parents RETURN v)
|
LET children = (FOR v IN 1 OUTBOUND ppp post_parents RETURN v)
|
||||||
UPDATE ppp WITH { answers_num : COUNT_DISTINCT( children[*]._key ) } IN posts"""
|
UPDATE ppp WITH { answers_num : COUNT_DISTINCT( children[*]._key ) } IN posts"""
|
||||||
)
|
)
|
||||||
|
cursor = db.aql.execute(
|
||||||
|
"""FOR ppp IN posts
|
||||||
|
LET children0 = (FOR v IN 1 OUTBOUND ppp post_parents RETURN v)
|
||||||
|
LET children = (FOR c IN children0
|
||||||
|
SORT c._key DESC
|
||||||
|
RETURN c)
|
||||||
|
UPDATE ppp WITH { answers_list : [ children[*]._key, children[*].answers_num, children[*].children_num ] } IN posts"""
|
||||||
|
)
|
||||||
|
|
||||||
postos = db.collection('posts')
|
postos = db.collection('posts')
|
||||||
postos = sorted(postos, key=lambda posto: posto['_key'], reverse=False)
|
postos = [ p for p in postos if (not p.get('root_post')) and p.get('thread') == thread ]
|
||||||
|
cursor = db.aql.execute(
|
||||||
|
f'RETURN DOCUMENT("posts/{thread}")'
|
||||||
|
)
|
||||||
|
postos.append(cursor.pop())
|
||||||
|
|
||||||
return render_template("i-posts.html", host_id=docker_short_id, postos=postos)
|
postos = sorted(postos, key=lambda posto: int(posto['_key']), reverse=False)
|
||||||
|
|
||||||
|
return render_template("i-posts.html", board=board, host_id=docker_short_id, postos=postos)
|
||||||
|
|
||||||
|
|
||||||
# @app.route('/post_my_file', method=['POST'])
|
|
||||||
# def post_a_file():
|
|
||||||
# pass
|
|
||||||
|
|
||||||
|
#### TODO websockets
|
||||||
### stolen
|
#### TODO sse
|
||||||
@app.route("/todo")
|
#### TODO kafka
|
||||||
def page_todo():
|
#### TODO shards
|
||||||
return render_template("page1.html")
|
#### TODO grpc
|
||||||
|
|
||||||
|
|
||||||
@app.route("/search", methods=["POST"])
|
|
||||||
def search_todo():
|
|
||||||
search_term = request.form.get("search")
|
|
||||||
|
|
||||||
if not len(search_term):
|
|
||||||
return render_template("todo.html", host_id=docker_short_id, todos=[])
|
|
||||||
|
|
||||||
res_todos = []
|
|
||||||
for todo in todos:
|
|
||||||
if search_term in todo["title"]:
|
|
||||||
res_todos.append(todo)
|
|
||||||
|
|
||||||
return render_template("todo.html", host_id=docker_short_id, todos=res_todos)
|
|
||||||
### /stolen
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3
reqs.txt
3
reqs.txt
@ -1,3 +1,4 @@
|
|||||||
flask
|
flask
|
||||||
flask-assets
|
flask-assets
|
||||||
python-arango
|
python-arango
|
||||||
|
minio
|
BIN
static/.webassets-cache/2823d3bed6298e1b3c14d859544819f8
Normal file
BIN
static/.webassets-cache/2823d3bed6298e1b3c14d859544819f8
Normal file
Binary file not shown.
BIN
static/.webassets-cache/88a59b23ca6148df558622ed8361e9d6
Normal file
BIN
static/.webassets-cache/88a59b23ca6148df558622ed8361e9d6
Normal file
Binary file not shown.
41
static/dist/main.css
vendored
Normal file
41
static/dist/main.css
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* украдено здесь https://css-tricks.com/hexagons-and-beyond-flexible-responsive-grid-patterns-sans-media-queries/ */
|
||||||
|
|
||||||
|
.hex-main {
|
||||||
|
display:flex;
|
||||||
|
--s: 100px; /* size */
|
||||||
|
--m: 4px; /* margin */
|
||||||
|
--f: calc(1.732 * var(--s) + 4 * var(--m) - 1px);
|
||||||
|
max-width: 440px;
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hex-container {
|
||||||
|
font-size: 0; /*disable white space between inline block element */
|
||||||
|
}
|
||||||
|
|
||||||
|
.hex-container img {
|
||||||
|
width: var(--s);
|
||||||
|
margin: var(--m);
|
||||||
|
height: calc(var(--s)*1.1547);
|
||||||
|
display: inline-block;
|
||||||
|
font-size:initial;
|
||||||
|
clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
|
||||||
|
background: transparent;
|
||||||
|
margin-bottom: calc(var(--m) - var(--s)*0.2885);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hex-container img:nth-child(odd) {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.hex-container::before {
|
||||||
|
content: "";
|
||||||
|
width: calc(var(--s)/2 + var(--m));
|
||||||
|
float: left;
|
||||||
|
height: 120%;
|
||||||
|
shape-outside: repeating-linear-gradient(
|
||||||
|
#0000 0 calc(var(--f) - 3px),
|
||||||
|
#000 0 var(--f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
1
static/src/_hyperscript.js
Normal file
1
static/src/_hyperscript.js
Normal file
File diff suppressed because one or more lines are too long
3567
static/src/htmx.js
3567
static/src/htmx.js
File diff suppressed because one or more lines are too long
69
templates/answer-post.html
Normal file
69
templates/answer-post.html
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<div class="card">
|
||||||
|
<form
|
||||||
|
hx-encoding='multipart/form-data'
|
||||||
|
_='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'
|
||||||
|
hx-on::after-request="this.reset()"
|
||||||
|
>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="row">
|
||||||
|
<span class="card-title">Ты отвечаешь: <a href="#post-{{ target_post_id }}">>>{{ target_post_id }}</a></span>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<a class="btn-floating halfway-fab waves-effect waves-light red" href="#post-{{ target_post_id }}"><i class="material-icons">>>{{ target_post_id }}</i></a>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s6">
|
||||||
|
<input id="send_this_text" name="send_this_text" type="text" >
|
||||||
|
<label for="send_this_text">Печатать сюда</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s6">
|
||||||
|
<div class="file-field input-field">
|
||||||
|
<div class="btn">
|
||||||
|
<span>File</span>
|
||||||
|
<input id="file" name="file" type="file" multiple>
|
||||||
|
</div>
|
||||||
|
<div class="file-path-wrapper">
|
||||||
|
<input class="file-path validate" type="text" placeholder="Upload one or more files">
|
||||||
|
<progress id='progress' value='0' max='100'></progress>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="file-progress">
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-action">
|
||||||
|
<a href="#answer-post">
|
||||||
|
<button class="btn waves-effect waves-light"
|
||||||
|
type="submit" name="action" hx-encoding='multipart/form-data'
|
||||||
|
_='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'
|
||||||
|
hx-post="/{{board}}/post_to_another_post/{{ target_post_id }}"
|
||||||
|
hx-target="#neu-posts"
|
||||||
|
hx-include="[name='send_this_text'], [name='file']"
|
||||||
|
>
|
||||||
|
Отправить!!
|
||||||
|
<i class="material-icons right">send</i>
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<!-- <div class="row">
|
||||||
|
<form hx-encoding='multipart/form-data' hx-post='/send_dudes'
|
||||||
|
_='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
|
||||||
|
<input type='file' name='file'>
|
||||||
|
<button>
|
||||||
|
Upload
|
||||||
|
</button>
|
||||||
|
<progress id='progress' value='0' max='100'></progress>
|
||||||
|
</form>
|
||||||
|
</div> -->
|
||||||
|
<!-- <h1>Загрузить картинку:</h1>
|
||||||
|
<input type="file" #file placeholder="Загрузить картинку" (change)="sendPic($event)" style="display:none;">
|
||||||
|
<button type="button" class="btn btn-success" (click)="file.click()">Загрузить картинку</button>
|
||||||
|
<div *ngFor="let singlePic of inputImages" >Картинка: {{singlePic}}</div>
|
||||||
|
<p>
|
||||||
|
<button (click)="eraseData()" >Убрать картинку</button>
|
||||||
|
</p> -->
|
||||||
|
</div>
|
@ -4,7 +4,16 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<!-- Compiled and minified CSS -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
|
||||||
|
<!-- Compiled and minified JavaScript -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://unpkg.com/htmx.org@1.9.3" integrity="sha384-lVb3Rd/Ca0AxaoZg5sACe8FJKF0tnUgR2Kd7ehUOG5GCcROv5uBIZsOqovBAcWua" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://unpkg.com/hyperscript.org@0.9.9"></script>
|
||||||
|
|
||||||
{% assets 'css' %}
|
{% assets 'css' %}
|
||||||
<link rel="stylesheet" href="{{ ASSET_URL }}">
|
<link rel="stylesheet" href="{{ ASSET_URL }}">
|
||||||
{% endassets %}
|
{% endassets %}
|
||||||
|
23
templates/board-posts.html
Normal file
23
templates/board-posts.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'navbar.html' %}
|
||||||
|
|
||||||
|
<div class="row" >
|
||||||
|
{% include 'create-thread.html' %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row" >
|
||||||
|
<div class="col s6 m5" id="op-posts">
|
||||||
|
{% include 'op-posts.html' %}
|
||||||
|
</div>
|
||||||
|
<!-- <div class="col s6 m5" id="thread-viz">
|
||||||
|
<iframe src="https://thread-visualizah-dev.board.vdk2ch.ru/" scrolling="no" frameborder="0" style="position: relative; height: 600px; width: 100%; margin:10px;"></iframe>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock content %}
|
@ -1,26 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<div class="content">
|
|
||||||
<p>Вы тут: /{{board_id}}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<nav>
|
|
||||||
<a href="/">glavnaya</a>
|
|
||||||
<br>
|
|
||||||
Доски:
|
|
||||||
<div class="boards">
|
|
||||||
<ul>
|
|
||||||
{% for board in boards %}
|
|
||||||
<li><a href="/boards/{{board}}">/{{board}}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
|
|
||||||
{% include 'posts.html' %}
|
|
||||||
|
|
||||||
{% endblock content %}
|
|
48
templates/create-thread.html
Normal file
48
templates/create-thread.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<div class="card">
|
||||||
|
<form
|
||||||
|
hx-encoding='multipart/form-data'
|
||||||
|
_='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'
|
||||||
|
hx-on::after-request="this.reset()"
|
||||||
|
>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="row">
|
||||||
|
<span class="card-title">Создавай тред уже!</span>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s6">
|
||||||
|
<input id="send_this_text" name="send_this_text" type="text" >
|
||||||
|
<label for="send_this_text">Печатать сюда</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s6">
|
||||||
|
<div class="file-field input-field">
|
||||||
|
<div class="btn">
|
||||||
|
<span>File</span>
|
||||||
|
<input id="file" name="file" type="file" multiple>
|
||||||
|
</div>
|
||||||
|
<div class="file-path-wrapper">
|
||||||
|
<input class="file-path validate" type="text" placeholder="Upload one or more files">
|
||||||
|
<progress id='progress' value='0' max='100'></progress>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="file-progress">
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-action">
|
||||||
|
<a href="/{{board}}/create-thread/{{ target_post_id }}">
|
||||||
|
<button class="btn waves-effect waves-light"
|
||||||
|
type="submit" name="action" hx-encoding='multipart/form-data'
|
||||||
|
_='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'
|
||||||
|
hx-post="/{{board}}/create-thread/{{ target_post_id }}"
|
||||||
|
hx-include="[name='send_this_text'], [name='file']"
|
||||||
|
>
|
||||||
|
Отправить!!
|
||||||
|
<i class="material-icons right">send</i>
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -2,23 +2,49 @@
|
|||||||
{% for posto in postos %}
|
{% for posto in postos %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% if posto.root_post %}
|
{% if posto.root_post %}
|
||||||
<div class="card s4 deep-orange accent-4 darken-1">
|
<div class="card s5 deep-orange accent-4 darken-1">
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="card s4 blue-grey darken-1">
|
<div class="card s5 blue-grey darken-1">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="card-content white-text">
|
||||||
|
<span class="new badge yellow" data-badge-caption="">
|
||||||
|
<a class="purple-text" href="#post-{{ posto._key }}"> #{{ posto._key }} </a>
|
||||||
|
</span>
|
||||||
|
<span class="new badge blue" data-badge-caption="">Ответов: {{ posto.answers_num }}</span>
|
||||||
|
<span class="new badge red" data-badge-caption="">Длина треда: {{ posto.children_num }}</span>
|
||||||
|
</div>
|
||||||
<div class="row" id="post-{{ posto._key }}">
|
<div class="row" id="post-{{ posto._key }}">
|
||||||
<div class="col s4">
|
|
||||||
<div class="card-image">
|
{% if posto.images | length > 0 %}
|
||||||
<div class="hex-main">
|
<div class="col s12">
|
||||||
|
<!-- <div class="hex-main">
|
||||||
<div class="hex-container">
|
<div class="hex-container">
|
||||||
<a href="https://loremflickr.com/g/320/240/paris" target="_blank" ">
|
<a href="https://loremflickr.com/g/320/240/paris" target="_blank" ">
|
||||||
<img src="https://loremflickr.com/g/320/240/paris">
|
<img src="https://loremflickr.com/g/320/240/paris">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
<div class="nav-wrapper">
|
||||||
|
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||||
|
<li>
|
||||||
|
<a href="https://static.guaranteedstruggle.host/thread-pics/photo_2023-05-16_00-49-34.jpg" target="_blank" ">
|
||||||
|
<img src="https://static.guaranteedstruggle.host/thread-pics/photo_2023-05-16_00-49-34.jpg" width="300px">
|
||||||
|
</a>
|
||||||
|
<span class=" "><a class="" href="https://static.guaranteedstruggle.host/thread-pics/photo_2023-05-16_00-49-34.jpg" target="_blank"> photo_2023-05-16_00-49-34.jpg </a> </span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://static.guaranteedstruggle.host/thread-pics/109.png" target="_blank" ">
|
||||||
|
<img src="https://static.guaranteedstruggle.host/thread-pics/109.png" width="300px">
|
||||||
|
</a>
|
||||||
|
<span class=" "><a class="" href="https://static.guaranteedstruggle.host/thread-pics/109.png" target="_blank"> 109.png </a> </span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col s8">
|
{% endif %}
|
||||||
|
<!-- <div class="col s8">
|
||||||
<div class="card-content white-text">
|
<div class="card-content white-text">
|
||||||
<span class="card-title">#{{ posto._key }}
|
<span class="card-title">#{{ posto._key }}
|
||||||
<span class="new badge blue" data-badge-caption="">Ответов: {{ posto.answers_num }}</span>
|
<span class="new badge blue" data-badge-caption="">Ответов: {{ posto.answers_num }}</span>
|
||||||
@ -26,14 +52,41 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
{% if posto.parent_post %}
|
{% if posto.parent_post %}
|
||||||
<a class="card-action" href="#post-{{ posto.parent_post }}"> >>{{ posto.parent_post }} </a>
|
<a class="link orange-text purple" href="#post-{{ posto.parent_post }}"> >>{{ posto.parent_post }} </a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p>{{ posto.texto }}</p>
|
<p>{{ posto.texto }}</p>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
<div class="col s12 card-content white-text">
|
||||||
|
{% if posto.parent_post %}
|
||||||
|
<a class="link orange-text purple" href="#post-{{ posto.parent_post }}"> >>{{ posto.parent_post }} </a>
|
||||||
|
{% endif %}
|
||||||
|
<p>{{ posto.texto }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col s12 card-action white-text">
|
||||||
|
<div class="right">
|
||||||
|
<!-- <a href="#" hx-post="/post_my_post/{{ posto._key }}" hx-target="#neu-posts" >Answer me!</a> -->
|
||||||
|
<a href="#answer-post" hx-post="/{{board}}/answer_post/{{ posto._key }}" hx-target="#answer-post" >Ответить этому.</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s12">
|
<div class="col s12 card-content white-text">
|
||||||
<div class="card-action right">
|
<!-- TODO !подгрузка следующего поста в конец треда без перезагрузки всего треда! -->
|
||||||
<a href="#" hx-post="/post_my_post/{{ posto._key }}" hx-target="#neu-posts" >Answer me!</a>
|
<div class="left">
|
||||||
|
<!-- <a href="#" hx-post="/post_my_post/{{ posto._key }}" hx-target="#neu-posts" >Answer me!</a> -->
|
||||||
|
{% if posto.answers_list[0] | length > 0 %}
|
||||||
|
<p>Ответы:</p>
|
||||||
|
{% for ans in posto.answers_list[0] %}
|
||||||
|
{% if (posto.answers_list[1])[loop.index-1] > 0 %}
|
||||||
|
{% if (posto.answers_list[2])[loop.index-1] > 0 %}
|
||||||
|
<a href="#post-{{ (posto.answers_list[0])[loop.index-1] }}" class="lime-text red collection-item" style="padding: 2px 2px;">>>{{ (posto.answers_list[0])[loop.index-1] }} (ответов {{ (posto.answers_list[1])[loop.index-1] }}, длина {{ (posto.answers_list[2])[loop.index-1] }})</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="#post-{{ (posto.answers_list[0])[loop.index-1] }}" class="lime-text red collection-item" style="padding: 2px 2px;">>>{{ (posto.answers_list[0])[loop.index-1] }} (ответов {{ (posto.answers_list[1])[loop.index-1] }})</a>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<a href="#post-{{ (posto.answers_list[0])[loop.index-1] }}" class="lime-text red collection-item" style="padding: 2px 2px;">>>{{ (posto.answers_list[0])[loop.index-1] }}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,13 +4,22 @@
|
|||||||
|
|
||||||
|
|
||||||
{% include 'navbar.html' %}
|
{% include 'navbar.html' %}
|
||||||
|
|
||||||
|
|
||||||
<div class="row" >
|
<div class="row" >
|
||||||
<div class="col s5" id="neu-posts">
|
<div class="col s6 m5" id="neu-posts">
|
||||||
{% include 'i-posts.html' %}
|
{% include 'i-posts.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col s6 m5" id="thread-viz">
|
||||||
|
<iframe src="https://thread-visualizah-dev.board.vdk2ch.ru/" scrolling="no" frameborder="0" style="position: relative; height: 600px; width: 100%; margin:10px;"></iframe>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s3 m3 " id="aa"></div>
|
||||||
|
<div class="col s7 m6 " id="answer-post">
|
||||||
|
{% include 'answer-post.html' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
@ -8,12 +8,10 @@
|
|||||||
<div class="col s4 center">
|
<div class="col s4 center">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-image">
|
<div class="card-image">
|
||||||
<img class="img-responsive" src="https://static.vdk2ch.ru/test-public/sin.jpg" height="400px" width="320px">
|
<img class="img-responsive" src="https://static.guaranteedstruggle.host/test-public/sin.jpg" height="400px" width="320px">
|
||||||
</div>
|
</div>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<p>
|
<p> Dobro pozhalovat. AGAIN. </p>
|
||||||
Dobro pozhalovat. AGAIN.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,12 @@
|
|||||||
<div class="nav-wrapper purple darken-3">
|
<div class="nav-wrapper purple darken-3">
|
||||||
<ul id="nav-mobile" class="left ">
|
<ul id="nav-mobile" class="left ">
|
||||||
<li> <a href="/">glavnaya</a> </li>
|
<li> <a href="/">glavnaya</a> </li>
|
||||||
<li><a href="/db_posts"><span class="new badge red" data-badge-caption="">here we go</span></a> </li>
|
|
||||||
|
{% if boards | length > 0 %}
|
||||||
|
{% for board in boards %}
|
||||||
|
<li><a href="/{{board}}"><span class="new badge red" data-badge-caption="">{{board}}</span></a> </li>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
<li>
|
<li>
|
||||||
<a href="#">Вас закинуло сюда: <span class="new badge blue" data-badge-caption="">{{host_id}}</span></a>
|
<a href="#">Вас закинуло сюда: <span class="new badge blue" data-badge-caption="">{{host_id}}</span></a>
|
||||||
</li>
|
</li>
|
||||||
|
53
templates/op-posts.html
Normal file
53
templates/op-posts.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{% if postos | length > 0 %}
|
||||||
|
{% for posto in postos %}
|
||||||
|
<div class="row">
|
||||||
|
{% if posto.root_post %}
|
||||||
|
<div class="card s5 deep-orange accent-4 darken-1">
|
||||||
|
{% else %}
|
||||||
|
<div class="card s5 blue-grey darken-1">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="card-content white-text">
|
||||||
|
<span class="new badge yellow" data-badge-caption="">
|
||||||
|
<a class="purple-text" href="/{{board}}/{{ posto._key }}"> #{{ posto._key }} </a>
|
||||||
|
</span>
|
||||||
|
<span class="new badge blue" data-badge-caption="">Ответов: {{ posto.answers_num }}</span>
|
||||||
|
<span class="new badge red" data-badge-caption="">Длина треда: {{ posto.children_num }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="row" id="post-{{ posto._key }}">
|
||||||
|
|
||||||
|
{% if posto.images | length > 0 %}
|
||||||
|
<div class="col s12">
|
||||||
|
<!-- <div class="nav-wrapper">
|
||||||
|
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||||
|
<li>
|
||||||
|
<a href="https://static.guaranteedstruggle.host/thread-pics/photo_2023-05-16_00-49-34.jpg" target="_blank" ">
|
||||||
|
<img src="https://static.guaranteedstruggle.host/thread-pics/photo_2023-05-16_00-49-34.jpg" width="300px">
|
||||||
|
</a>
|
||||||
|
<span class=" "><a class="" href="https://static.guaranteedstruggle.host/thread-pics/photo_2023-05-16_00-49-34.jpg" target="_blank"> photo_2023-05-16_00-49-34.jpg </a> </span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://static.guaranteedstruggle.host/thread-pics/109.png" target="_blank" ">
|
||||||
|
<img src="https://static.guaranteedstruggle.host/thread-pics/109.png" width="300px">
|
||||||
|
</a>
|
||||||
|
<span class=" "><a class="" href="https://static.guaranteedstruggle.host/thread-pics/109.png" target="_blank"> 109.png </a> </span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="col s12 card-content white-text">
|
||||||
|
<p>{{ posto.texto }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col s12 card-action white-text">
|
||||||
|
<div class="right">
|
||||||
|
<!-- <a href="#" hx-post="/post_my_post/{{ posto._key }}" hx-target="#neu-posts" >Answer me!</a> -->
|
||||||
|
<a href="/{{board}}/{{ posto._key }}" >В тред!</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
@ -1,36 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<div class="panel-block">
|
|
||||||
|
|
||||||
<div class="w-small w-2/3 mx-auto py-10 text-gray-600">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="search"
|
|
||||||
hx-post="/search"
|
|
||||||
hx-trigger="keyup changed delay:250ms"
|
|
||||||
hx-indicator=".htmx-indicator"
|
|
||||||
hx-target="#todo-results"
|
|
||||||
placeholder="Search"
|
|
||||||
class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
|
|
||||||
>
|
|
||||||
<span class="htmx-indicator">Searching...</span>
|
|
||||||
</div>
|
|
||||||
+dev 3
|
|
||||||
|
|
||||||
|
|
||||||
<table class="border-collapse w-small w-2/3 mx-auto">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
|
|
||||||
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
|
|
||||||
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody id="todo-results">
|
|
||||||
{% include 'todo.html' %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% endblock content %}
|
|
@ -1,75 +0,0 @@
|
|||||||
{% if board_threads|length>0 %}
|
|
||||||
{% for thread in board_threads %}
|
|
||||||
<div class="post post_type_reply post_withimg" id="post-15135655" data-num="15135655">
|
|
||||||
<div class="post__details" id="post-details-15135655">
|
|
||||||
<input type="checkbox" name="delete" class="turnmeoff" value="15135655">
|
|
||||||
<span class="post__detailpart">
|
|
||||||
<span class="post__anon">{{thread.name}}</span>
|
|
||||||
</span>
|
|
||||||
<span class="post__detailpart">
|
|
||||||
<span class="post__time">05/07/23 Срд 14:53:58</span>
|
|
||||||
</span>
|
|
||||||
<span class="post__detailpart">
|
|
||||||
<a href="/news/res/15135633.html#15135655" id="15135655" class="post__reflink">№</a>
|
|
||||||
<a href="/news/res/15135633.html#15135655" class="js-post-reply-btn post__reflink" data-num="15135655">{{thread.post_num}}</a>
|
|
||||||
<span class="post__number">2</span></span>
|
|
||||||
<span class="post__detailpart">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="post__btn post__btn_type_menu icon desktop" data-num="15135655"><use xlink:href="#icon__addmenu"></use></svg>
|
|
||||||
<span data-num="15135655" onclick="addAdminMenu(this); return false;" onmouseout="removeAdminMenu(event); return false;" style="display: flex;">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="post__btn post__btn_type_adm icon"><use xlink:href="#icon__report"></use></svg>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="post__images post__images_type_multi">
|
|
||||||
<!-- <div class="post__images">
|
|
||||||
<svg class="post__file-preview " data-width="954" data-height="960" data-type="2" data-md5="15135655-d39bd5b1ed6c40e9a1d1eb2971a57584" data-title="image.png" viewBox="0 0 100 100" data-src="https://static.vdk2ch.ru/thread-pics/{{pic}}" width="168" height="170" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<defs>
|
|
||||||
<pattern id="img-{{thread.post_num}}" patternUnits="userSpaceOnUse" width="100" height="100">
|
|
||||||
<image xlink:href="https://static.vdk2ch.ru/thread-pics/{{pic}}" x="-25" width="150" height="100" />
|
|
||||||
</pattern>
|
|
||||||
</defs>
|
|
||||||
<use>
|
|
||||||
<polygon points="50 1 95 25 95 75 50 99 5 75 5 25" fill="url(#img-{{thread.post_num}})"/>
|
|
||||||
</use>
|
|
||||||
</svg>
|
|
||||||
</div> -->
|
|
||||||
<!-- <figure class="post__image">
|
|
||||||
<figcaption class="post__file-attr">
|
|
||||||
<a class="desktop" target="_blank" href="https://static.vdk2ch.ru/thread-pics/{{pic}}" title="image.png">{{pic}}</a>
|
|
||||||
|
|
||||||
</figcaption> -->
|
|
||||||
<!-- <svg visibility="visible" class="post__file-preview " data-width="954" data-height="960" data-type="2" data-md5="15135655-d39bd5b1ed6c40e9a1d1eb2971a57584" data-title="image.png" viewBox="0 0 100 100" data-src="https://static.vdk2ch.ru/thread-pics/{{pic}}" width="168" height="170" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<defs>
|
|
||||||
<pattern id="img-{{thread.post_num}}" patternUnits="userSpaceOnUse" width="100" height="100">
|
|
||||||
<image xlink:href="https://static.vdk2ch.ru/thread-pics/{{pic}}" x="-25" width="150" height="100" />
|
|
||||||
</pattern>
|
|
||||||
</defs>
|
|
||||||
<use>
|
|
||||||
<polygon points="50 1 95 25 95 75 50 99 5 75 5 25" fill="url(#img-{{thread.post_num}})"/>
|
|
||||||
</use>
|
|
||||||
</svg> -->
|
|
||||||
|
|
||||||
<!-- <img src="https://static.vdk2ch.ru/thread-pics/{{pic}}" alt="954x960" id="img-15135655-d39bd5b1ed6c40e9a1d1eb2971a57584" class="post__file-preview " data-type="2" data-title="image.png" data-width="954" data-height="960" data-md5="15135655-d39bd5b1ed6c40e9a1d1eb2971a57584" data-src="https://static.vdk2ch.ru/thread-pics/{{pic}}" width="168" height="170"> -->
|
|
||||||
<!-- </figure> -->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="hex-main">
|
|
||||||
<div class="hex-container">
|
|
||||||
{% for pic in thread.pic_links %}
|
|
||||||
<a href="https://static.vdk2ch.ru/thread-pics/{{pic}}" target="_blank" ">
|
|
||||||
<img src="https://static.vdk2ch.ru/thread-pics/{{pic}}" >
|
|
||||||
</a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<article id="m15135655" class="post__message ">
|
|
||||||
<a href="/news/res/15135633.html#15135633" class="post-reply-link" data-thread="15135633" data-num="15135633">>>15135633 (OP)</a><br>
|
|
||||||
|
|
||||||
{{thread.txt}}
|
|
||||||
</article>
|
|
||||||
<div id="refmap-15135655" class="post__refmap" style="display: none;"></div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
@ -1,15 +0,0 @@
|
|||||||
{% if todos|length>0 %}
|
|
||||||
{% for todo in todos %}
|
|
||||||
<tr class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
|
|
||||||
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">{{todo.id}}</td>
|
|
||||||
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">{{todo.title}}</td>
|
|
||||||
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
|
|
||||||
{% if todo.completed %}
|
|
||||||
<span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
11
threads.py
11
threads.py
@ -1,11 +0,0 @@
|
|||||||
threads_lists = {
|
|
||||||
'b': {
|
|
||||||
'123','124'
|
|
||||||
},
|
|
||||||
'a': {
|
|
||||||
'1'
|
|
||||||
},
|
|
||||||
'd': {
|
|
||||||
'44','99','1230'
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
# <id>: {<post_num>, <pic_links>, <texto>, <name>}
|
|
||||||
open_threads = {
|
|
||||||
'123': {
|
|
||||||
'thread_num': '123',
|
|
||||||
'post_num': '9999',
|
|
||||||
'pic_links': ['16216445863900.jpg'],
|
|
||||||
'txt': 'фыва',
|
|
||||||
'name': 'anonius'
|
|
||||||
},
|
|
||||||
'124': {
|
|
||||||
'thread_num': '124',
|
|
||||||
'post_num': '456',
|
|
||||||
'pic_linkss': ['16672846165910.png'],
|
|
||||||
'txt': 'Test',
|
|
||||||
'name': 'anonius'
|
|
||||||
},
|
|
||||||
'1': {
|
|
||||||
'thread_num': '123',
|
|
||||||
'post_num': '1',
|
|
||||||
'pic_links': ['16211265989190.jpg'],
|
|
||||||
'txt': 'фыва',
|
|
||||||
'name': 'anonius'
|
|
||||||
},
|
|
||||||
'44': {
|
|
||||||
'thread_num': '44',
|
|
||||||
'post_num': '12',
|
|
||||||
'pic_links': ['15937598937440.png'],
|
|
||||||
'txt': 'I hate my brother-nation..',
|
|
||||||
'name': 'Владимир Владимирович'
|
|
||||||
},
|
|
||||||
'99': {
|
|
||||||
'thread_num': '99',
|
|
||||||
'post_num': '55',
|
|
||||||
'pic_links': ['Экран-смерти.jpg','Экран-смерти.jpg','Экран-смерти.jpg','Экран-смерти.jpg','15937598937440.png','Экран-смерти.jpg','Экран-смерти.jpg'],
|
|
||||||
'txt': 'фыва',
|
|
||||||
'name': 'anonius'
|
|
||||||
},
|
|
||||||
'1230': {
|
|
||||||
'thread_num': '1230',
|
|
||||||
'post_num': '1234',
|
|
||||||
'pic_links': ['15906018690140.png'],
|
|
||||||
'txt': '33333!',
|
|
||||||
'name': 'SIRNA'
|
|
||||||
}
|
|
||||||
}
|
|
457
todo.py
457
todo.py
@ -1,457 +0,0 @@
|
|||||||
todos = [
|
|
||||||
{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 2,
|
|
||||||
"title": "quis ut nam facilis et officia qui",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 1, "id": 3, "title": "fugiat veniam minus", "completed": False},
|
|
||||||
{"userId": 1, "id": 4, "title": "et porro tempora", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 5,
|
|
||||||
"title": "laboriosam mollitia et enim quasi adipisci quia provident illum",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 6,
|
|
||||||
"title": "qui ullam ratione quibusdam voluptatem quia omnis",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 7,
|
|
||||||
"title": "illo expedita consequatur quia in",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 1, "id": 8, "title": "quo adipisci enim quam ut ab", "completed": True},
|
|
||||||
{"userId": 1, "id": 9, "title": "molestiae perspiciatis ipsa", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 10,
|
|
||||||
"title": "illo est ratione doloremque quia maiores aut",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 1, "id": 11, "title": "vero rerum temporibus dolor", "completed": True},
|
|
||||||
{"userId": 1, "id": 12, "title": "ipsa repellendus fugit nisi", "completed": True},
|
|
||||||
{"userId": 1, "id": 13, "title": "et doloremque nulla", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 14,
|
|
||||||
"title": "repellendus sunt dolores architecto voluptatum",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 1, "id": 15, "title": "ab voluptatum amet voluptas", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 16,
|
|
||||||
"title": "accusamus eos facilis sint et aut voluptatem",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 17,
|
|
||||||
"title": "quo laboriosam deleniti aut qui",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 18,
|
|
||||||
"title": "dolorum est consequatur ea mollitia in culpa",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 19,
|
|
||||||
"title": "molestiae ipsa aut voluptatibus pariatur dolor nihil",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 1,
|
|
||||||
"id": 20,
|
|
||||||
"title": "ullam nobis libero sapiente ad optio sint",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 21,
|
|
||||||
"title": "suscipit repellat esse quibusdam voluptatem incidunt",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 22,
|
|
||||||
"title": "distinctio vitae autem nihil ut molestias quo",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 23,
|
|
||||||
"title": "et itaque necessitatibus maxime molestiae qui quas velit",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 24,
|
|
||||||
"title": "adipisci non ad dicta qui amet quaerat doloribus ea",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 25,
|
|
||||||
"title": "voluptas quo tenetur perspiciatis explicabo natus",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 2, "id": 26, "title": "aliquam aut quasi", "completed": True},
|
|
||||||
{"userId": 2, "id": 27, "title": "veritatis pariatur delectus", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 28,
|
|
||||||
"title": "nesciunt totam sit blanditiis sit",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 2, "id": 29, "title": "laborum aut in quam", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 30,
|
|
||||||
"title": "nemo perspiciatis repellat ut dolor libero commodi blanditiis omnis",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 31,
|
|
||||||
"title": "repudiandae totam in est sint facere fuga",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 32,
|
|
||||||
"title": "earum doloribus ea doloremque quis",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 2, "id": 33, "title": "sint sit aut vero", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 34,
|
|
||||||
"title": "porro aut necessitatibus eaque distinctio",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 35,
|
|
||||||
"title": "repellendus veritatis molestias dicta incidunt",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 36,
|
|
||||||
"title": "excepturi deleniti adipisci voluptatem et neque optio illum ad",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 2, "id": 37, "title": "sunt cum tempora", "completed": False},
|
|
||||||
{"userId": 2, "id": 38, "title": "totam quia non", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 2,
|
|
||||||
"id": 39,
|
|
||||||
"title": "doloremque quibusdam asperiores libero corrupti illum qui omnis",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 2, "id": 40, "title": "totam atque quo nesciunt", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 41,
|
|
||||||
"title": "aliquid amet impedit consequatur aspernatur placeat eaque fugiat suscipit",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 42,
|
|
||||||
"title": "rerum perferendis error quia ut eveniet",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 43,
|
|
||||||
"title": "tempore ut sint quis recusandae",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 44,
|
|
||||||
"title": "cum debitis quis accusamus doloremque ipsa natus sapiente omnis",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 45,
|
|
||||||
"title": "velit soluta adipisci molestias reiciendis harum",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 46,
|
|
||||||
"title": "vel voluptatem repellat nihil placeat corporis",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 47,
|
|
||||||
"title": "nam qui rerum fugiat accusamus",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 48,
|
|
||||||
"title": "sit reprehenderit omnis quia",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 49,
|
|
||||||
"title": "ut necessitatibus aut maiores debitis officia blanditiis velit et",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 50,
|
|
||||||
"title": "cupiditate necessitatibus ullam aut quis dolor voluptate",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 51,
|
|
||||||
"title": "distinctio exercitationem ab doloribus",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 52,
|
|
||||||
"title": "nesciunt dolorum quis recusandae ad pariatur ratione",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 53,
|
|
||||||
"title": "qui labore est occaecati recusandae aliquid quam",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 54,
|
|
||||||
"title": "quis et est ut voluptate quam dolor",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 55,
|
|
||||||
"title": "voluptatum omnis minima qui occaecati provident nulla voluptatem ratione",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 3, "id": 56, "title": "deleniti ea temporibus enim", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 57,
|
|
||||||
"title": "pariatur et magnam ea doloribus similique voluptatem rerum quia",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 58,
|
|
||||||
"title": "est dicta totam qui explicabo doloribus qui dignissimos",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 59,
|
|
||||||
"title": "perspiciatis velit id laborum placeat iusto et aliquam odio",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 3,
|
|
||||||
"id": 60,
|
|
||||||
"title": "et sequi qui architecto ut adipisci",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 4, "id": 61, "title": "odit optio omnis qui sunt", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 62,
|
|
||||||
"title": "et placeat et tempore aspernatur sint numquam",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 63,
|
|
||||||
"title": "doloremque aut dolores quidem fuga qui nulla",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 64,
|
|
||||||
"title": "voluptas consequatur qui ut quia magnam nemo esse",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 65,
|
|
||||||
"title": "fugiat pariatur ratione ut asperiores necessitatibus magni",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 66,
|
|
||||||
"title": "rerum eum molestias autem voluptatum sit optio",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 67,
|
|
||||||
"title": "quia voluptatibus voluptatem quos similique maiores repellat",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 68,
|
|
||||||
"title": "aut id perspiciatis voluptatem iusto",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 69,
|
|
||||||
"title": "doloribus sint dolorum ab adipisci itaque dignissimos aliquam suscipit",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 70,
|
|
||||||
"title": "ut sequi accusantium et mollitia delectus sunt",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 4, "id": 71, "title": "aut velit saepe ullam", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 72,
|
|
||||||
"title": "praesentium facilis facere quis harum voluptatibus voluptatem eum",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 73,
|
|
||||||
"title": "sint amet quia totam corporis qui exercitationem commodi",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 74,
|
|
||||||
"title": "expedita tempore nobis eveniet laborum maiores",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 75,
|
|
||||||
"title": "occaecati adipisci est possimus totam",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 4, "id": 76, "title": "sequi dolorem sed", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 77,
|
|
||||||
"title": "maiores aut nesciunt delectus exercitationem vel assumenda eligendi at",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 78,
|
|
||||||
"title": "reiciendis est magnam amet nemo iste recusandae impedit quaerat",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 4, "id": 79, "title": "eum ipsa maxime ut", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 4,
|
|
||||||
"id": 80,
|
|
||||||
"title": "tempore molestias dolores rerum sequi voluptates ipsum consequatur",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 5, "id": 81, "title": "suscipit qui totam", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 82,
|
|
||||||
"title": "voluptates eum voluptas et dicta",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 83,
|
|
||||||
"title": "quidem at rerum quis ex aut sit quam",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 5, "id": 84, "title": "sunt veritatis ut voluptate", "completed": False},
|
|
||||||
{"userId": 5, "id": 85, "title": "et quia ad iste a", "completed": True},
|
|
||||||
{"userId": 5, "id": 86, "title": "incidunt ut saepe autem", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 87,
|
|
||||||
"title": "laudantium quae eligendi consequatur quia et vero autem",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 88,
|
|
||||||
"title": "vitae aut excepturi laboriosam sint aliquam et et accusantium",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{"userId": 5, "id": 89, "title": "sequi ut omnis et", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 90,
|
|
||||||
"title": "molestiae nisi accusantium tenetur dolorem et",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 91,
|
|
||||||
"title": "nulla quis consequatur saepe qui id expedita",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 5, "id": 92, "title": "in omnis laboriosam", "completed": True},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 93,
|
|
||||||
"title": "odio iure consequatur molestiae quibusdam necessitatibus quia sint",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 5, "id": 94, "title": "facilis modi saepe mollitia", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 95,
|
|
||||||
"title": "vel nihil et molestiae iusto assumenda nemo quo ut",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 96,
|
|
||||||
"title": "nobis suscipit ducimus enim asperiores voluptas",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 97,
|
|
||||||
"title": "dolorum laboriosam eos qui iure aliquam",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 98,
|
|
||||||
"title": "debitis accusantium ut quo facilis nihil quis sapiente necessitatibus",
|
|
||||||
"completed": True,
|
|
||||||
},
|
|
||||||
{"userId": 5, "id": 99, "title": "neque voluptates ratione", "completed": False},
|
|
||||||
{
|
|
||||||
"userId": 5,
|
|
||||||
"id": 100,
|
|
||||||
"title": "excepturi a et neque qui expedita vel voluptate",
|
|
||||||
"completed": False,
|
|
||||||
},
|
|
||||||
]
|
|
Loading…
Reference in New Issue
Block a user