Compare commits

...

87 Commits

Author SHA1 Message Date
t
9c6c5524a8 Back to old model. 2023-11-28 00:08:28 +03:00
none
482d53af93 Fix 2023-11-27 21:01:07 +03:00
none
891f7fecf2 Change port 2023-11-27 20:40:06 +03:00
none
0f0b29e03e Merge branch 'main' of ssh://5.180.137.216:2222/justuser/pxl_oboard 2023-11-27 20:37:42 +03:00
justuser
0280863e74 Delete 'site/design.css' 2023-11-27 23:36:29 +03:00
justuser
d3b74c80e0 Delete 'site/site.html' 2023-11-27 23:36:09 +03:00
none
d1cf3552bf Update style, dark theme, change names, no css. 2023-11-27 20:37:33 +03:00
none
9b260c1975 Merge branch 'main' of ssh://5.180.137.216:2222/justuser/pxl_oboard 2023-11-27 20:24:25 +03:00
t
58a4545a40 Merge remote-tracking branch 'refs/remotes/origin/main' 2023-11-27 23:00:17 +03:00
t
4dc9452156 Speed up to 2x token. 2023-11-27 22:57:59 +03:00
t
6abc4c4691 Add token-system 2023-11-27 21:29:08 +03:00
none
5f1e1c88d7 Update 2023-11-27 20:13:30 +03:00
none
2801b14b05 Fix token-error. 2023-11-27 18:42:02 +03:00
none
3b73faa794 Customizeable limit and token-system. 2023-11-27 18:30:32 +03:00
none
83b43cdd5b Add Holinim's site auto-update version 2023-11-26 21:39:06 +03:00
none
276bcb7ff9 Fix wrong cords. 2023-11-26 18:37:29 +03:00
none
87938079b3 Add image-preview + cords of this image. 2023-11-26 18:04:43 +03:00
none
cc3bc15ac8 Separate threads, now cords more faster. 2023-11-26 14:22:31 +03:00
justuser
77f0a2a19d Update 'map.py' 2023-11-26 16:48:39 +03:00
none
1b5a86b0a2 Back map.py (temp) 2023-11-25 22:04:53 +03:00
justuser
00c58c925d revert 35426ab931
revert Delete 'map.py'
2023-11-26 00:59:30 +03:00
none
abc2025032 Little change example. 2023-11-25 21:26:18 +03:00
none
38e68ce92d Fix mirror-bug. 2023-11-25 20:53:37 +03:00
none
161e8cb728 Fix flip-bug, now convert normally image. 2023-11-25 17:57:05 +03:00
none
a561b1a08b New image draw and optimizer 🎉 2023-11-25 15:24:47 +03:00
justuser
4373dab299 Delete 'im_convert.py' 2023-11-25 16:40:16 +03:00
justuser
cb4b642a70 Rename botv2 to bot 2023-11-25 16:39:42 +03:00
justuser
4f6c2190d6 Delete 'bot.py' 2023-11-25 16:39:10 +03:00
none
41f70c6cf2 Stable version 2023-11-25 13:14:22 +03:00
t
c3dad58e41 . 2023-11-25 16:08:57 +03:00
none
edcaf98b42 New beta. Remove pack() in extras (no longer needed) 2023-11-25 00:48:05 +03:00
t
3bf33f9d30 Change resolution to 1280x720 - 16:9 2023-11-25 03:39:46 +03:00
t
05d983dae3 Add limit for post (draw pixels) 2023-11-25 02:15:16 +03:00
none
19eadd9d81 Fix cpu/speed, beta-version 2023-11-24 22:53:05 +03:00
none
1faf6301b6 New beta-version 2023-11-24 22:04:35 +03:00
none
60852d1ad0 New v2 with arrays post and get ( [[x,y], [x,y]] ) 2023-11-23 22:27:46 +03:00
justuser
955f383031 Delete 'server.py' 2023-11-24 01:25:25 +03:00
justuser
d9a47dfd55 Delete 'post.py' 2023-11-24 01:25:10 +03:00
justuser
41756716e7 Delete 'map.png' 2023-11-23 19:17:36 +03:00
justuser
70207f351f Delete 'image.png' 2023-11-23 19:17:20 +03:00
justuser
35426ab931 Delete 'map.py' 2023-11-23 19:17:09 +03:00
justuser31
910dd6e62f Maked show image before move input 2023-05-26 22:29:21 +03:00
justuser31
56e5458814 Update adress 2023-05-12 17:53:39 +03:00
justuser31
d57189b086 Rename main.py to server.py 2023-04-26 17:39:39 +03:00
justuser
8b30ab0ec8 Rename to server.py 2023-04-26 17:37:04 +03:00
justuser
6203bf186f Delete 'im_create.py' 2023-04-24 17:43:14 +03:00
justuser
b14283af8d Update 'README.md' 2023-04-24 17:40:47 +03:00
justuser31
5d6923aaf6 Optimize support 2023-04-23 21:07:56 +03:00
justuser31
0263b7bc6f Make it better 2023-04-23 19:35:26 +03:00
justuser31
2c81b71556 More colors and structuring color codes 2023-04-23 13:45:30 +03:00
justuser31
13afd1dfee dark_green -> green 2023-04-23 12:07:21 +03:00
justuser31
56fea85607 Add more colors 2023-04-23 12:03:19 +03:00
justuser31
60ca1f4bb3 Show percent of removed pixels 2023-04-22 20:04:06 +03:00
justuser31
e8f5b8dba9 Background remover 2023-04-22 19:59:30 +03:00
justuser31
44a6990a4c Fix bar 2023-04-22 15:39:48 +03:00
justuser31
b0db41c11a Icon for map.py 2023-04-22 15:38:29 +03:00
justuser31
fada354c74 Add icon and add cordinates 2023-04-22 15:31:49 +03:00
justuser31
faecbf0fc6 Init real-time map 2023-04-22 14:34:31 +03:00
justuser31
fac9ac8dcc Disable rotation 2023-04-22 13:49:32 +03:00
justuser31
83ef33480a Remove upscale: it's buggy 2023-04-22 13:47:07 +03:00
justuser31
ee2e6e96e4 Fix visual bug 2023-04-22 12:53:44 +03:00
justuser31
9145838701 Init image for im_converter.py 2023-04-22 12:41:32 +03:00
justuser31
3aff64a933 Enable online mode 2023-04-22 12:40:48 +03:00
justuser31
afbfa02566 Disable pixel check: it glitched 2023-04-22 12:40:09 +03:00
justuser31
1b87107d3c Init image converter 2023-04-22 12:39:01 +03:00
justuser31
1b415d50c5 Merge branch 'main' of ssh://ssh.dmcraft.online:2222/justuser/pxl_oboard 2023-04-21 20:48:40 +03:00
justuser31
4f5e14e131 Pass colored pixels 2023-04-21 20:48:27 +03:00
Your Name
380930e8e7 Fix colors 2023-04-21 20:40:58 +03:00
justuser31
df06ca94a3 Revert 2023-04-21 20:22:39 +03:00
justuser31
f5ed42c5e6 Revert 2023-04-21 20:22:17 +03:00
justuser31
74ad0ad523 Revert x y 2023-04-21 20:17:44 +03:00
justuser31
16930a2770 Init get_color 2023-04-21 20:14:38 +03:00
justuser31
3ad7d6f6fc Remove delay 2023-04-21 18:32:50 +03:00
justuser31
855e80f6e5 Remove borders 2023-04-21 18:32:25 +03:00
justuser31
f87c84db30 Add draw line 2023-04-21 17:19:58 +03:00
justuser31
10dab6a7f5 Merge branch 'main' of ssh://ssh.dmcraft.online:2222/justuser/pxl_oboard 2023-04-21 16:51:44 +03:00
justuser31
864a07cd89 Add move at X and Y 2023-04-21 16:50:46 +03:00
justuser
67762fda4a Update 'README.md' 2023-04-21 16:11:45 +03:00
justuser31
c8c6b2f405 Merge branch 'main' of ssh://ssh.dmcraft.online:2222/justuser/pxl_oboard 2023-04-21 16:06:37 +03:00
justuser31
ae874feb75 Add x and y move in draw() 2023-04-21 16:06:24 +03:00
justuser
d3b4728c3c Update 'README.md' 2023-04-21 15:44:32 +03:00
justuser31
99ec1d099d Wait after error and no wait before request 2023-04-21 15:41:35 +03:00
justuser31
9a83760295 Compatibility for python 3.7 2023-04-21 15:19:23 +03:00
justuser31
e0995302eb Compatibility for python 3.7 2023-04-21 15:16:53 +03:00
justuser31
33c335b001 Add progress bar 2023-04-21 13:01:59 +03:00
justuser31
35574ef69f Merge branch 'main' of ssh://ssh.dmcraft.online:2222/justuser/pxl_oboard 2023-04-21 12:55:44 +03:00
justuser31
3b72176d9c Add fill() and progress bar 2023-04-21 12:55:30 +03:00
16 changed files with 609 additions and 267 deletions

View File

@ -9,21 +9,39 @@ Super simple, super stupid.
## -------------------------------- ## --------------------------------
## >>>Рисование<<<: ## >>>Рисование<<<:
## Уровень: ламер ## Уровень: ламер
1. Скачать im_creator.py 1. Скачать im_convert.py
2. Запустить через `python3 im_creator.py` 2. Запустить через `python3 im_creator.py`
3. Нарисовать что-то. 3. Загрузить/нарисовать изображение, файл - image.png где и скрипт. (желательно не больше 128 на 128 пикселей)
4. Нажать кнопку "Upload" для загрузки рисунка на сервер. 4. Задать смещение по координатам X и Y.
5. Ждать надписи в консоли "DONE" 5. Проверить результат - должно показать конвертированное изображение.
6. Включить/выключить оптимизацию. ( (Y/N), оно убирает фоновый цвет, чем уменьшеает время на отрисовку)
7. Загрузить изображение. (Y)
## Уровень: овнокодер ## Уровень: овнокодер (типо документация)
Вы можете написать свой скрипт на основе post.py или... Вы можете написать свой скрипт на основе post.py (почти ничего нету) или...
1. Скачать bot.py 1. Скачать bot.py
2. Запрогроммировать свои инструкции для бота: 2. Запрогроммировать свои инструкции для бота:
#### draw([0,1], [0,2]) - Функция для рисования, использует массив списков. ### Функция gcolor(x, y)
( Поставить точки в координатах [0,1] и [0,2] формата [x,y] ) - Принимает на вход два параметра: x и y - координаты пикселя на сайте.
#### linex(y, x1, x2) - Функция для создания массива линии по координате Х - Возвращает цвет пикселя, например: "white" (белый).
( Y остаётся таким же, массив идёт из x1 в x2 )
#### liney(x, y1, y2) - Аналогично. ### Функция draw(cords, color = "black")
- Принимает на вход список cords - список координат для точек.
- Опциональный параметр color, для изменения цвета. ( полезно только для списков из fill()/linex()/liney() )
- Возвращает строку "DONE!" после отрисовки.
### Функция linex(y, x1, x2)
- Принимает на вход три параметра: y - координата Y, x1 - первая координата X, x2 - вторая кордината X.
- Создаёт массив координат: линия из [x1, y] в [x2, y].
- !! x2 должен быть больше x1 !!
- Возвращает массив координат, можно передать в draw()
### Функция liney(x, y1, y2)
- Аналогично, только по Y.
### Функция fill(xy1, xy2)
- Принимает на вход два параметра: xy1 и xy2 - координаты двух точек прямоугольника для заливки.
- Возвращает массив координат, можно передать в draw()
## -------------------------------- ## --------------------------------
## Установка своего сервера: ## Установка своего сервера:

123
bot.py
View File

@ -1,58 +1,87 @@
import requests import requests
from time import sleep from time import sleep
# Progress-bar
from tqdm import tqdm
# Work with list-like objects
from listwork import *
def draw(cords): # Easy debug
for i in range(len(cords)): from icecream import ic
sleep(0.2) ic.disable() # Disable debug
try:
payload = {'x': cords[i][1], 'y': cords[i][0], 'color': cords[i][2]}
except:
payload = {'x': cords[i][1], 'y': cords[i][0], 'color': "blue" }
response = requests.post('http://pb.dmcraft.online', data=payload)
print(response)
while str(response) != "<Response [200]>":
response = requests.post('http://pb.dmcraft.online', data=payload)
print("Retrying...")
print(response)
print("DONE!")
def linex(y, x1, x2): global server
res = [] #server = 'http://127.0.0.1:3333'
for i in range(x1, x2+1): server = 'http://pb.gulyaipole.fun'
res.append( [i,y] )
return res
def liney(x, y1, y2): # fill(0,0, 10,10, [0,0,0])
res = [] def fill(x1,y1, x2,y2, color):
for i in range(y1, y2+1): pxls = []
res.append( [x,i] ) r = color[0] ; g = color[1] ; b = color[2]
return res for x in range(x1, x2+1):
for y in range(y1, y2+1):
pxls.append([x, y, r, g, b])
return pxls
# draw( fill(...), limit=500, token="fdsfs" )
def draw(pxls, limit=300, token="None"):
global server
ic(pxls)
push = [] # Push %limit% items
while len(pxls) > limit:
packs = [] # Merge elements to %limit% size list
for i in range(limit):
# Take first element
packs.append(pxls[0])
pxls.pop(0)
push.append({"main": pack(packs), "token": token})
push.append({"main": pack(pxls), "token": token}) # Pack last
ic(push)
for i in tqdm(push):
response = requests.post(server, i)
while not response.status_code == 200:
print("Error, retrying...")
response = requests.post(server, i)
sleep(0.1)
# cfill(0,0, 10,10) // Limit - 34x34
def cfill(x1,y1, x2,y2):
pxls = []
for x in range(x1, x2+1):
for y in range(y1, y2+1):
pxls.append([x, y])
packed = pack(pxls)
return packed
# ccheck( packed([[0,0]]) ) or ccheck(cfill(...))
def ccheck(packed):
global server
response = requests.get(f'{server}/get_color={packed}')
ic(response.text)
out = unpack(response.text)
return out
l = [[65, 86, 'red'], [66, 87, 'red'], [66, 86, 'red'], [66, 85, 'red'], [67, 86, 'red'], [89, 97, 'red'], [90, 98, 'red'], [90, 97, 'red'], [90, 96, 'red'], [91, 97, 'red'], [95, 77, 'black'], [96, 78, 'black'], [96, 77, 'black'], [96, 76, 'black'], [97, 77, 'black'], [107, 108, 'blue'], [108, 109, 'blue'], [108, 108, 'blue'], [108, 107, 'blue'], [109, 108, 'blue']]
draw(l) ### EXAMPLE
# Draw random square 100x100 on 0,0
from random import randint as ri
draw( fill(0,0, 100,100, [ri(0,255),ri(0,255),ri(0,255)]) )
# Check square 34x34 on 0,0
print(ccheck(cfill(0,0, 34,34)))
#draw( liney(300, 300, 500) ) # Use extras, draw 1/2 random square 100x100 on 0,0
#draw(linex(500, 300, 500)) from bot_extras import *
draw(pas2( rand(0,0, 100,100) ))
''' # Draw image (flipped (BUG) )
xs = 180 from im_convert import *
ys = 180 image = convert("example.png", [10,0])
#S from remove_back import *
cords = [ [3+xs,0+ys],[2+xs,0+ys],[1+xs,0+ys],[1+xs,-1+ys],[1+xs,-2+ys],[2+xs,-2+ys],[3+xs,-2+ys],[3+xs,-3+ys],[3+xs,-4+ys],[2+xs,-4+ys],[1+xs,-4+ys] ] draw( optimize(image, [255,255,255]) ) # Remove white background and draw
draw(cords)
#A # Draw with premium-token, limit 600 (default token)
cords = [ [5+xs,-4+ys],[5+xs,-3+ys],[5+xs,-2+ys],[5+xs,-1+ys],[5+xs,0+ys],[6+xs,0+ys],[7+xs,0+ys],[8+xs,0+ys],[8+xs,-4+ys],[8+xs,-3+ys],[8+xs,-2+ys],[8+xs,-1+ys],[8+xs,0+ys],[5+xs,-2+ys],[6+xs,-2+ys],[7+xs,-2+ys],[8+xs,-2+ys], ] # Token is fake, >ERROR<
draw(cords) draw( fill(758,0, 1123,198, [255,255,255]), limit=600, token="3744138bd462cd8180e4w3534rfdsw4rwert" )
#N
cords = [ [10+xs,-4+ys],[10+xs,-3+ys],[10+xs,-2+ys],[10+xs,-1+ys],[10+xs,0+ys],[11+xs,-1+ys],[12+xs,-2+ys],[13+xs,-3+ys],[14+xs,-4+ys],[15+xs,-4+ys],[15+xs,-3+ys],[15+xs,-2+ys],[15+xs,-1+ys],[15+xs,0+ys], ]
draw(cords)
#S
xs = xs + 16
cords = [ [3+xs,0+ys],[2+xs,0+ys],[1+xs,0+ys],[1+xs,-1+ys],[1+xs,-2+ys],[2+xs,-2+ys],[3+xs,-2+ys],[3+xs,-3+ys],[3+xs,-4+ys],[2+xs,-4+ys],[1+xs,-4+ys] ]
draw(cords)
'''

23
bot_extras.py Normal file
View File

@ -0,0 +1,23 @@
from listwork import *
from random import randint as ri
# pas2( fill(...) ) -> 1/2
def pas2(pxls):
new_pxls = []
pas = False
for i in pxls:
if not pas:
new_pxls.append(i)
pas = True
else:
pas = False
return new_pxls
# rand(x1,y1, x2,y2) -> draw() or pas2()
def rand(x1,y1, x2,y2):
pxls = []
for x in range(x1, x2 +1):
for y in range(y1, y2 +1):
pxls.append([x,y, ri(0,255), ri(0,255), ri(0,255)])
return pxls

BIN
example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

42
gpt_blob.py Normal file
View File

@ -0,0 +1,42 @@
import tkinter as tk
from time import sleep
def start_drag(event):
global current_coords
global dragged_item
dragged_item = label
current_coords = label.winfo_pointerx(), label.winfo_pointery()
def stop_drag(event):
dragged_item = None
def drag(event):
global current_coords
xc, yc = label.winfo_pointerx(), label.winfo_pointery()
dx, dy = xc - current_coords[0], yc - current_coords[1]
current_coords = xc, yc
label.place(x=label.winfo_x() + dx, y=label.winfo_y() + dy)
def nn(root,im):
global label
image = tk.PhotoImage(file=im) # Use self.image
label = tk.Label(root, image=image)
label.image = image # Keep a reference to the image
label.pack()
dragged_item = None
current_coords = 0, 0
label.bind('<ButtonPress-1>', start_drag)
label.bind('<ButtonRelease-1>', stop_drag)
label.bind('<B1-Motion>', drag)
# globals().update(locals())
while True:
tk.Misc.lift(label)
sleep(0.05)
print("Image cords: ", label.winfo_x(), 720 - label.winfo_y() - image.height())
#x1, y1 = image.coords(image)
# print(f'Image cords: {}')

52
im_convert.py Normal file
View File

@ -0,0 +1,52 @@
from PIL import Image, ImageOps
# [[0,0, rgb1],... [1,1, rgb2]] -> [[1,1, rgb1],...[0,0, rgb2]]
def flip(cords):
fliped = []
flips = len(cords)//2
# El from start and el from end
fl0 = 0 ; fl1 = len(cords)-1
for i in range(flips):
# Copy element and change cords to cords of end element
new_st = list(cords[fl0])
new_st[0] = cords[fl1][0]
new_st[1] = cords[fl1][1]
fliped.append(new_st)
# Copy and change cords to cords of start element
new_end = list(cords[fl1])
new_end[0] = cords[fl0][0]
new_end[1] = cords[fl0][1]
fliped.append(new_end)
fl0 += 1 ; fl1 -= 1
return fliped
# convert("example.png") // png/jpg/gif
def convert(filename, move = [0,0]):
im = Image.open(filename).convert('RGB')
# Fix mirror
im = ImageOps.mirror(im)
pxls=im.load()
w=im.size[0]
h=im.size[1]
ll = []
for x in range(w):
for y in range(h):
# [x,y, [r, g, b]]
rgb = pxls[x,y]
ll.append( [x,y, rgb[0], rgb[1], rgb[2] ] )
# Fix flip
fliped = flip(ll)
# Move [x,y] + move
moved = []
for i in fliped:
moved.append([i[0] + move[0], i[1] + move[1], i[2],i[3],i[4]])
return moved

View File

@ -1,115 +0,0 @@
from tkinter import *
####DRAW BLOCK
import requests
from time import sleep
def draw(cords):
for i in range(len(cords)):
sleep(0.2)
try:
payload = {'x': cords[i][1], 'y': cords[i][0], 'color': cords[i][2]}
except:
payload = {'x': cords[i][1], 'y': cords[i][0], 'color': "b" }
response = requests.post('http://pb.dmcraft.online', data=payload)
print(response)
while str(response) != "<Response [200]>":
response = requests.post('http://pb.dmcraft.online', data=payload)
print("Retrying...")
print(response)
print("!!!DONE!!!")
class PixelArt:
def __init__(self, master):
self.master = master
self.master.title("Pixel Art")
self.canvas = Canvas(self.master, width=128*12, height=128*12, bg="white")
self.canvas.pack(side=LEFT, padx=5, pady=5)
self.colors = ["red", "green", "blue", "white","black"]
self.current_color = "red"
self.button_frame = Frame(self.master)
self.button_frame.pack(side=LEFT, padx=5, pady=5)
self.export_button = Button(self.button_frame, text="Export", command=self.export_image)
self.export_button.pack(side=TOP, padx=5, pady=5)
self.button_frame.pack(side=LEFT, padx=5, pady=5)
self.export_button = Button(self.button_frame, text="Clean", command=self.clean_image)
self.export_button.pack(side=TOP, padx=5, pady=5)
self.button_frame.pack(side=LEFT, padx=5, pady=5)
self.export_button = Button(self.button_frame, text="Upload", command=self.upload_image)
self.export_button.pack(side=TOP, padx=5, pady=5)
self.color_buttons = []
for color in self.colors:
button = Button(self.button_frame, bg=color, width=3, height=1, command=lambda c=color: self.set_color(c))
button.pack(side=TOP, padx=5, pady=5)
self.color_buttons.append(button)
for i in range(129):
self.canvas.create_line(i*12, 0, i*12, 128*12, fill="white")
self.canvas.create_line(0, i*12, 128*12, i*12, fill="white")
self.canvas.bind("<Button-1>", self.draw_pixel)
def draw_pixel(self, event):
x = int(event.x / 12)
y = int(event.y / 12)
self.canvas.create_rectangle(x*12, y*12, x*12 + 12, y*12 + 12, fill=self.current_color)
def set_color(self, color):
self.current_color = color
def clean_image(self):
items = self.canvas.find_all()
for item in items:
self.canvas.delete(item)
def upload_image(self):
pixel_data = []
for i in range(128):
for j in range(128):
color = self.canvas.itemcget(self.canvas.find_closest(i*12+6, j*12+6), "fill")
if color != "white":
match self.colors.index(color):
case 0:
color = "red"
case 1:
color = "green"
case 2:
color = "blue"
case 3:
color = "black"
pixel_data.append([i, 127-j, color])
print("!!!START UPLOAD!!!")
draw(pixel_data)
def export_image(self):
pixel_data = []
for i in range(128):
for j in range(128):
color = self.canvas.itemcget(self.canvas.find_closest(i*12+6, j*12+6), "fill")
if color != "white":
match self.colors.index(color):
case 0:
color = "red"
case 1:
color = "green"
case 2:
color = "blue"
case 3:
color = "black"
pixel_data.append([i, 127-j, color])
f = open('out.txt', 'w')
f.write(str(pixel_data))
f.close()
if __name__ == "__main__":
root = Tk()
pixel_art = PixelArt(root)
root.mainloop()

24
listwork.py Normal file
View File

@ -0,0 +1,24 @@
def unpack(string):
ll = string.split('-_')
ll.remove("") # Remove empty line
el_col = ll[0].count('-')
post_ll = []
for i in ll:
temp = i.split("-")
# Multi-add (2, 3 or 5 elements)
if el_col == 1:
post_ll.append([int(temp[0]), int(temp[1])])
elif el_col == 2:
post_ll.append([int(temp[0]), int(temp[1]), int(temp[2])])
elif el_col == 4:
post_ll.append([int(temp[0]), int(temp[1]), int(temp[2]), int(temp[3]), int(temp[4]) ])
return post_ll
def pack(ll):
string = ''
for el in ll:
for i in el:
string += str(i) + '-'
string += '_'
return string

90
main.py
View File

@ -1,90 +0,0 @@
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
from io import BytesIO
from PIL import Image
import numpy as np
import time
global LTIME
LTIME = cur_time = time.monotonic()
class RequestHandler(BaseHTTPRequestHandler):
MATRIX_SIZE = (800, 1024)
COLORS = {
'w': (255, 255, 255),
'b': (0, 0, 0),
'r': (255, 0, 0),
'g': (0, 255, 0),
}
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'image/png')
self.end_headers()
matrix = self.get_matrix()
matrix = np.flip(matrix, axis=0)
self.send_image(matrix)
def do_POST(self):
global LTIME
cur_time = time.monotonic()
address = self.client_address[0]
print("IP: ", address)
if cur_time - LTIME <= 0.01:
self.send_error(429, 'Too Many Requests')
self.send_response(429)
return 0
else:
LTIME = time.monotonic()
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
params = parse_qs(body.decode('utf-8'))
y = int(params['y'][0])
x = int(params['x'][0])
color = params['color'][0]
matrix = self.get_matrix()
matrix[x][y] = self.COLORS[color]
self.save_matrix(matrix)
self.send_response(302)
self.send_header('Location', '/')
self.end_headers()
def get_matrix(self):
try:
with open('matrix.npy', 'rb') as f:
matrix = np.load(f)
except FileNotFoundError:
matrix = np.full(shape=(*self.MATRIX_SIZE, 3), fill_value=255, dtype=np.uint8)
self.save_matrix(matrix)
return matrix
def save_matrix(self, matrix):
with open('matrix.npy', 'wb') as f:
np.save(f, matrix)
def send_image(self, matrix):
image = Image.fromarray(matrix)
buffer = BytesIO()
image.save(buffer, format='PNG')
self.wfile.write(buffer.getvalue())
def run():
server = HTTPServer(('127.0.0.1', 3333), RequestHandler)
server.serve_forever()
if __name__ == '__main__':
run()

88
map.py Normal file
View File

@ -0,0 +1,88 @@
import urllib.request
import time
from PIL import Image, ImageTk
import io
import tkinter as tk
url = "https://pb.gulyaipole.fun/"
root = tk.Tk()
root.geometry("1280x720")
# Canvas for image
canvas = tk.Canvas(root)
canvas.pack()
# XY cords
ttext = tk.Canvas(root, width=100, height=20, bg="black")
ttext.place(x=1180, y=0)
text = ttext.create_text(50, 10, text="X: 1, Y: 1", fill="white")
# Run threads
from threading import Thread
from time import sleep
def cords_up():
while True:
x = root.winfo_pointerx() - root.winfo_rootx()
y = 720 - (root.winfo_pointery() - root.winfo_rooty())
ttext.itemconfig(text, text=f"X: {x}, Y: {y}")
sleep(0.05)
cords = Thread(target=cords_up)
cords.start()
#### WARN, GPT-BLOB ####
from gpt_blob import *
# Get file from args
from sys import argv
try:
im = argv[1]
n = Thread(target=nn, args=[root, im,])
n.start()
except:
print("None image")
#######################
def map_up():
global canvas_old, canvas, label
while True:
# Prepare image for tkiner
image_file = io.BytesIO(urllib.request.urlopen(url).read())
img = Image.open(image_file)
tk_img = ImageTk.PhotoImage(img)
# Create new canvas
canvas = tk.Canvas(root, width=img.size[0], height=img.size[1])
canvas.create_image(0, 0, anchor="nw", image=tk_img)
canvas.place(x=0, y=0)
try:
# New canvas and cords up
tk.Misc.lift(canvas)
tk.Misc.lift(ttext)
# Update
root.update()
sleep(2)
# Remove old
canvas_old.destroy()
except:
pass
# New canvas now is old
canvas_old = canvas
map = Thread(target=map_up)
map.start()
root.mainloop()

21
post.py
View File

@ -1,6 +1,19 @@
import requests import requests
# Work with list-like objects
from listwork import *
server = 'http://127.0.0.1:3333'
# Draw some pixels
# [[x, y, color-1, color-2, color-3], ...]
fill = {"main": pack([[200, 100, 0, 0, 0], [15, 30, 255, 54, 43]]) }
response = requests.post(server, data=fill)
if response:
print("posted")
# Get color code of coords
# [[x,y], ...]
xys = pack([[200,100], [13,10], [50,50]])
response = requests.get(f'{server}/get_color={xys}')
print( unpack(response.text) )
payload = {'x': 52, 'y': 20, 'color': 'r'}
#response = requests.post('http://pb.dmcraft.online', data=payload)
response = requests.post('http://127.0.0.1:3333', data=payload)
print(response)

16
remove_back.py Normal file
View File

@ -0,0 +1,16 @@
from tqdm import tqdm
def optimize(pxls, back):
old_len = len(pxls)
new_pxls = []
for i in tqdm(range(old_len)):
el = pxls[i]
now_back = [el[2], el[3], el[4]]
if now_back != back:
new_pxls.append(pxls[i])
print(f"Optimized {(old_len - len(new_pxls)) / old_len * 100 }%")
return new_pxls

167
server.py Normal file
View File

@ -0,0 +1,167 @@
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
from io import BytesIO
from PIL import Image
import numpy as np
import time
# Easy debug
from icecream import ic
ic.disable() # Turn off
# Limit for requests
LTIME = cur_time = time.monotonic()
globals().update(locals())
# Key by value
def kbv(dict_, value):
for i in dict_:
if dict_[i] == value:
return i
# Work with list-like objects
from listwork import *
# Work with tokens
import json
global tokens
def tokens_load():
with open('tokens.json', 'r') as openfile:
return json.load(openfile)
# (Re)generate tokens
def tokens_regen():
import hashlib
from random import randint as ri
tokens = tokens_load()
tokens["admin"] = hashlib.sha256(str.encode( str(ri(2443, 6543)) + tokens["secret"] )).hexdigest()
tokens["premium"] = []
for i in range(10):
tokens["premium"].append( hashlib.sha256(str.encode( str(ri(2443, 6543)) + tokens["secret"] )).hexdigest() )
js = json.dumps(tokens, indent=2)
with open("tokens.json", "w") as outfile:
outfile.write(js)
# Uncomment to regen
#tokens_regen()
class RequestHandler(BaseHTTPRequestHandler):
MATRIX_SIZE = (720, 1280)
def do_GET(self):
params = parse_qs(self.path[1:])
ic(params)
if 'get_color' in params:
params = params['get_color'][0]
ic(len(params))
xys = unpack(params)
ic.disable()
matrix = self.get_matrix()
colors = []
for i in xys:
ic(i)
x = i[0] ; y = i[1]
color = matrix[x][y]
ic(color)
colors.append(color)
colors = pack(colors)
ic(colors)
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(f'{colors}'.encode())
else:
self.send_response(200)
self.send_header('Content-type', 'image/png')
self.end_headers()
matrix = self.get_matrix()
matrix = np.flip(matrix, axis=0) #Fix flip on server side
self.send_image(matrix)
def do_POST(self):
global LTIME
cur_time = time.monotonic()
if cur_time - LTIME <= 0.0001:
self.send_error(429, 'Too Many Requests')
self.send_response(429)
return 0
else:
LTIME = time.monotonic()
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
params = parse_qs(body.decode('utf-8'))["main"][0]
ic(params)
# Parse token
ic( parse_qs(body.decode('utf-8')) )
token = parse_qs(body.decode('utf-8'))["token"][0]
#Set limit pixels for 1 response
ic(len(params))
if len(params) > 6700:
# Get tokens
tokens = tokens_load()
# Admin's token
if token[0] == tokens["admin"][0]:
pass
elif token[0] in tokens["premium"] and len(params) < 13400:
pass
else:
return 0
matrix = self.get_matrix()
ll = unpack(params)
for i in ll:
x = i[1] ; y = i[0] #Fix (y, x) -> (x, y) on server side
matrix[x, y] = [i[2], i[3], i[4]]
self.save_matrix(matrix)
self.send_response(302)
self.send_header('Location', '/')
self.end_headers()
def get_matrix(self):
try:
with open('matrix.npy', 'rb') as f:
matrix = np.load(f)
except FileNotFoundError:
matrix = np.full(shape=(*self.MATRIX_SIZE, 3), fill_value=255, dtype=np.uint8)
self.save_matrix(matrix)
return matrix
def save_matrix(self, matrix):
with open('matrix.npy', 'wb') as f:
np.save(f, matrix)
def send_image(self, matrix):
image = Image.fromarray(matrix)
buffer = BytesIO()
image.save(buffer, format='PNG')
self.wfile.write(buffer.getvalue())
def run():
server = HTTPServer(('127.0.0.1', 3333), RequestHandler)
server.serve_forever()
while True:
try:
run()
print(1)
except KeyboardInterrupt:
exit()
except:
pass

1
site/README.md Normal file
View File

@ -0,0 +1 @@
Special thanks to Holinim.

37
site/index.html Normal file
View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PixelBoard</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&family=Nunito:wght@300&display=swap" rel="stylesheet">
<script>
setInterval(function() {
var image = document.getElementById('PBImage');
image.src = 'http://pb.gulyaipole.fun/' + new Date().getTime();
}, 2000);
</script>
</head>
<body bgcolor="#DAA06D"> <!--Old color - #1c5ca6-->
<button onclick="window.location.href='live_black.html';" style='background-color:#7e4a12; border-radius: 1000px'>
<img src="https://cdn.icon-icons.com/icons2/1674/PNG/32/moon_111148.png">
</button>
<p align = "center"><b><font face="Montserrat" size='5' width="500">Пиксельная доска</font></b></p>
<p align = "center">
<img id="PBImage" src="http://pb.gulyaipole.fun:3333" onclick="window.location.href='https://pb.gulyaipole.fun:3333'" height=640 style="border: 8px solid #dbac83">
<br>
<button onclick="window.location.href='https://gitea.gulyaipole.fun/justuser/pxl_oboard';" style="background-color: #c5792d; border-radius: 1000px">
<font face="Montserrat" width="400">Репозиторий проекта</font>
</button>
<button onclick="window.location.href='https://docs.google.com/document/d/1hEccpHxwDQrpTW7RMmf3lqYtJIDh1Fwb';" style="background-color: #c5792d; border-radius: 1000px">
<font face="Montserrat" width="400">Как рисовать на доске?</font>
</button>
<button onclick="window.location.href='https://t.me/pxl_oboard';" style="background-color: #c5792d; border-radius: 1000px">
<font face="Montserrat" width="400">Telegram проекта</font>
</button>
<br><br>
<b><font face="Montserrat" width="300">Правила проекта:</font></b>
<font face="Nunito"><br>1. Уважать других - не перекрывать/закрашивать чужие рисунки<br>2. Рисунки не должны представлять из себя 18+ контент или пропаганду LGBT.<br>3. Рисунки не должны нарушать законы Российской Федерации.</font>
</body>
</html>

37
site/live_black.html Normal file
View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PixelBoard</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&family=Nunito:wght@300&display=swap" rel="stylesheet">
<script>
setInterval(function() {
var image = document.getElementById('PBImage');
image.src = 'http://pb.gulyaipole.fun/' + new Date().getTime();
}, 2000);
</script>
</head>
<body bgcolor="#06111f">
<button onclick="window.location.href='index.html';" style='background-color:#0484da; border-radius: 1000px'>
<img src="https://cdn.icon-icons.com/icons2/1325/PNG/32/fun4x_86984.png">
</button>
<p align = "center"><b><font face="Montserrat" size='5' width="500" color='white'>Пиксельная доска</font></b></p>
<p align = "center">
<img id="PBImage" src="http://pb.gulyaipole.fun:3333" onclick="window.location.href='https://pb.gulyaipole.fun:3333'" height=640 style="border: 8px solid #101655">
<br>
<button onclick="window.location.href='https://gitea.gulyaipole.fun/justuser/pxl_oboard';" style="background-color: #112f4d; border-radius: 1000px">
<font face="Montserrat" color='white' width="400">Репозиторий проекта</font>
</button>
<button onclick="window.location.href='https://docs.google.com/document/d/1hEccpHxwDQrpTW7RMmf3lqYtJIDh1Fwb';" style="background-color: #112f4d; border-radius: 1000px">
<font face="Montserrat" color='white' width="400">Как рисовать на доске?</font>
</button>
<button onclick="window.location.href='https://t.me/pxl_oboard';" style="background-color: #112f4d; border-radius: 1000px">
<font face="Montserrat" color='white' width="400">Telegram проекта</font>
</button>
<br><br>
<b><font face="Montserrat" color='white' width="300">Правила проекта:</font></b>
<font face="Nunito" color='white'><br>1. Уважать других - не перекрывать/закрашивать чужие рисунки<br>2. Рисунки не должны представлять из себя 18+ контент или пропаганду LGBT.<br>3. Рисунки не должны нарушать законы Российской Федерации.</font>
</body>
</html>