remove requests dependency from areaDownload.py

This commit is contained in:
HF 2023-10-01 00:03:57 +02:00
parent ed154a0737
commit d79636ae88
2 changed files with 83 additions and 45 deletions

View File

@ -30,6 +30,7 @@ Script to move canvas chunks, i.e. for resizing canvas
downloads an area of the canvas into a png file. downloads an area of the canvas into a png file.
Usage: `areaDownload.py startX_startY endX_endY filename.png` Usage: `areaDownload.py startX_startY endX_endY filename.png`
(note that you can copy the current coordinates in this format on the site by pressing R) (note that you can copy the current coordinates in this format on the site by pressing R)
**Requires:** aiohttp, asyncio and PIL python3 packages
## historyDownload.py ## historyDownload.py
downloads the history from an canvas area between two dates. downloads the history from an canvas area between two dates.

View File

@ -1,13 +1,12 @@
#!/usr/bin/python3 #!/usr/bin/python3
import PIL.Image import PIL.Image
import sys, os, io import sys, os, io, math
import asyncio import asyncio
import aiohttp import aiohttp
import requests
import math
apime = requests.get('https://pixelplanet.fun/api/me').json() USER_AGENT = "ppfun areaDownload 1.0"
PPFUN_URL = "https://pixelplanet.fun"
class Color(object): class Color(object):
def __init__(self, index, rgb): def __init__(self, index, rgb):
@ -18,8 +17,8 @@ class EnumColorPixelplanet:
ENUM = [] ENUM = []
def getColors(canvasid): def getColors(canvas):
colors = apime['canvases'][canvasid]['colors'] colors = canvas['colors']
for i, color in enumerate(colors): for i, color in enumerate(colors):
EnumColorPixelplanet.ENUM.append(Color(i, tuple(color))) EnumColorPixelplanet.ENUM.append(Color(i, tuple(color)))
@ -82,12 +81,36 @@ class Matrix:
self.matrix[x] = {} self.matrix[x] = {}
self.matrix[x][y] = color self.matrix[x][y] = color
async def fetchMe():
url = f"{PPFUN_URL}/api/me"
headers = {
'User-Agent': USER_AGENT
}
async with aiohttp.ClientSession() as session:
attempts = 0
while True:
try:
async with session.get(url, headers=headers) as resp:
data = await resp.json()
return data
except:
if attempts > 3:
print(f"Could not get {url} in three tries, cancelling")
raise
attempts += 1
print(f"Failed to load {url}, trying again in 5s")
await asyncio.sleep(5)
pass
async def fetch(session, canvasID, canvasoffset, ix, iy, target_matrix): async def fetch(session, canvasID, canvasoffset, ix, iy, target_matrix):
url = f'https://pixelplanet.fun/chunks/{canvasID}/{ix}/{iy}.bmp' url = f"{PPFUN_URL}/chunks/{canvasID}/{ix}/{iy}.bmp"
headers = {
'User-Agent': USER_AGENT
}
attempts = 0 attempts = 0
while True: while True:
try: try:
async with session.get(url) as resp: async with session.get(url, headers=headers) as resp:
data = await resp.read() data = await resp.read()
offset = int(-canvasoffset * canvasoffset / 2) offset = int(-canvasoffset * canvasoffset / 2)
off_x = ix * 256 + offset off_x = ix * 256 + offset
@ -110,14 +133,17 @@ async def fetch(session, canvasID, canvasoffset, ix, iy, target_matrix):
break break
except: except:
if attempts > 3: if attempts > 3:
print(f"Could not get {url} in three tries, cancelling")
raise raise
attempts += 1 attempts += 1
print(f"Failed to load {url}, trying again in 3s")
await asyncio.sleep(3)
pass pass
async def get_area(canvasID, x, y, w, h): async def get_area(canvasID, canvas, x, y, w, h):
target_matrix = Matrix() target_matrix = Matrix()
target_matrix.add_coords(x, y, w, h) target_matrix.add_coords(x, y, w, h)
canvasoffset = math.pow(apime["canvases"][f"{canvasID}"]["size"], 0.5) canvasoffset = math.pow(canvas['size'], 0.5)
offset = int(-canvasoffset * canvasoffset / 2) offset = int(-canvasoffset * canvasoffset / 2)
xc = (x - offset) // 256 xc = (x - offset) // 256
wc = (x + w - offset) // 256 wc = (x + w - offset) // 256
@ -134,30 +160,30 @@ async def get_area(canvasID, x, y, w, h):
def validateCoorRange(ulcoor: str, brcoor: str, canvasSize: int): # stolen from hf with love def validateCoorRange(ulcoor: str, brcoor: str, canvasSize: int): # stolen from hf with love
if not ulcoor or not brcoor: if not ulcoor or not brcoor:
return 'Not all coordinates defined' return "Not all coordinates defined"
splitCoords = ulcoor.strip().split('_') splitCoords = ulcoor.strip().split('_')
if not len(splitCoords) == 2: if not len(splitCoords) == 2:
return 'Invalid Coordinate Format for top-left corner' return "Invalid Coordinate Format for top-left corner"
x, y = map(lambda z: int(math.floor(float(z))), splitCoords) x, y = map(lambda z: int(math.floor(float(z))), splitCoords)
splitCoords = brcoor.strip().split('_') splitCoords = brcoor.strip().split('_')
if not len(splitCoords) == 2: if not len(splitCoords) == 2:
return 'Invalid Coordinate Format for top-left corner' return "Invalid Coordinate Format for top-left corner"
u, v = map(lambda z: int(math.floor(float(z))), splitCoords) u, v = map(lambda z: int(math.floor(float(z))), splitCoords)
error = None error = None
if (math.isnan(x)): if (math.isnan(x)):
error = 'x of top-left corner is not a valid number' error = "x of top-left corner is not a valid number"
elif (math.isnan(y)): elif (math.isnan(y)):
error = 'y of top-left corner is not a valid number' error = "y of top-left corner is not a valid number"
elif (math.isnan(u)): elif (math.isnan(u)):
error = 'x of bottom-right corner is not a valid number' error = "x of bottom-right corner is not a valid number"
elif (math.isnan(v)): elif (math.isnan(v)):
error = 'y of bottom-right corner is not a valid number' error = "y of bottom-right corner is not a valid number"
elif (u < x or v < y): elif (u < x or v < y):
error = 'Corner coordinates are aligned wrong' error = "Corner coordinates are aligned wrong"
if not error is None: if not error is None:
return error return error
@ -166,44 +192,55 @@ def validateCoorRange(ulcoor: str, brcoor: str, canvasSize: int): # stolen from
canvasMinXY = -canvasMaxXY canvasMinXY = -canvasMaxXY
if (x < canvasMinXY or y < canvasMinXY or x >= canvasMaxXY or y >= canvasMaxXY): if (x < canvasMinXY or y < canvasMinXY or x >= canvasMaxXY or y >= canvasMaxXY):
return 'Coordinates of top-left corner are outside of canvas' return "Coordinates of top-left corner are outside of canvas"
if (u < canvasMinXY or v < canvasMinXY or u >= canvasMaxXY or v >= canvasMaxXY): if (u < canvasMinXY or v < canvasMinXY or u >= canvasMaxXY or v >= canvasMaxXY):
return 'Coordinates of bottom-right corner are outside of canvas' return "Coordinates of bottom-right corner are outside of canvas"
return (x, y, u, v) return (x, y, u, v)
if __name__ == "__main__": async def main():
apime = await fetchMe()
if len(sys.argv) != 5: if len(sys.argv) != 5:
print("Download an area of pixelplanet") print("Download an area of pixelplanet")
print("Usage: areaDownload.py canvasID startX_startY endX_endY filename.png") print("Usage: areaDownload.py canvasID startX_startY endX_endY filename.png")
print("(use R key on pixelplanet to copy coordinates)") print("(use R key on pixelplanet to copy coordinates)")
print("Canvas ID: ", end='') print("canvasID: ", end='')
for canvas in apime['canvases']: for canvasID, canvas in apime['canvases'].items():
if canvas == '2': if 'v' in canvas and canvas['v']:
continue continue
print(f"{canvas} = {apime['canvases'][f'{canvas}']['title']}", end=' ') print(f"{canvasID} = {canvas['title']}", end=', ')
print() print()
return
canvasID = sys.argv[1]
if canvasID not in apime['canvases']:
print("Invalid canvas selected")
return
canvas = apime['canvases'][canvasID]
if 'v' in canvas and canvas['v']:
print("Can\'t get area for 3D canvas")
return
parseCoords = validateCoorRange(sys.argv[2], sys.argv[3], canvas['size'])
if (type(parseCoords) is str):
print(parseCoords)
sys.exit()
else: else:
canvasID = sys.argv[1] x, y, w, h = parseCoords
w = w - x + 1
h = h - y + 1
if canvasID == '2': EnumColorPixelplanet.getColors(canvas)
print('Can\'t get area for 3D canvas') filename = sys.argv[4]
sys.exit()
parseCoords = validateCoorRange(sys.argv[2], sys.argv[3], apime["canvases"][f"{canvasID}"]["size"]) matrix = await get_area(canvasID, canvas, x, y, w, h)
matrix.create_image(filename)
print("Done!")
if (type(parseCoords) is str): if __name__ == "__main__":
print(parseCoords) asyncio.run(main())
sys.exit()
else:
x, y, w, h = parseCoords
w = w - x + 1
h = h - y + 1
EnumColorPixelplanet.getColors(canvasID)
filename = sys.argv[4]
loop = asyncio.new_event_loop()
matrix = loop.run_until_complete(get_area(canvasID, x, y, w, h))
matrix.create_image(filename)
print("Done!")