finish canvas link parsing

This commit is contained in:
HF 2022-01-16 14:56:46 +01:00
parent a6fd5b7962
commit f2035f9660
10 changed files with 87 additions and 42 deletions

View File

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
scp -r ./src/* pixelplanet:~/ppfun-bridge/src/ scp -r ./src/* pixelplanet:~/ppfun-bridge/src/
scp ./*.js pixelplanet:~/ppfun-bridge/ scp ./*.js pixelplanet:~/ppfun-bridge/
scp ./*.json pixelplanet:~/ppfun-bridge/
ssh pixelplanet 'pm2 stop ppfun-bridge; cd ~/ppfun-bridge; pm2 start ecosystem.yml' ssh pixelplanet 'pm2 stop ppfun-bridge; cd ~/ppfun-bridge; pm2 start ecosystem.yml'

View File

@ -3,7 +3,7 @@
// node index.js -r -u "http://localhost:9000" # remember to add the registration! // node index.js -r -u "http://localhost:9000" # remember to add the registration!
// node index.js -p 9000 // node index.js -p 9000
const PPfunMatrixBridge = require('./src/ppfunMatrixBridge'); import PPfunMatrixBridge from './src/ppfunMatrixBridge.js';
const PORT = parseInt(process.env.PORT, 10) || 8009; const PORT = parseInt(process.env.PORT, 10) || 8009;
const APISOCKET_KEY = process.env.APISOCKET_KEY || ''; const APISOCKET_KEY = process.env.APISOCKET_KEY || '';

View File

@ -124,4 +124,4 @@ class Palette {
} }
} }
module.exports = Palette; export default Palette;

View File

@ -1,12 +1,13 @@
const Palette = require('./Palette'); import Palette from './Palette.js';
const { import fetch from 'node-fetch';
import {
TILE_SIZE, TILE_SIZE,
TILE_ZOOM_LEVEL, TILE_ZOOM_LEVEL,
} = require('./constants'); } from './constants.js';
let canvases = new Map(); let canvases = new Map();
function fetchCanvasData() { async function fetchCanvasData() {
try { try {
const response = await fetch('https://pixelplanet.fun/api/me'); const response = await fetch('https://pixelplanet.fun/api/me');
if (response.status >= 300) { if (response.status >= 300) {
@ -21,9 +22,8 @@ function fetchCanvasData() {
canvas.id = id; canvas.id = id;
canvas.palette = new Palette(canvas.colors); canvas.palette = new Palette(canvas.colors);
canvas.maxTiledZoom = Math.log2(canvas.size / TILE_SIZE) / TILE_ZOOM_LEVEL * 2; canvas.maxTiledZoom = Math.log2(canvas.size / TILE_SIZE) / TILE_ZOOM_LEVEL * 2;
canvasMap.set(canvas.ident, canvas); canvases.set(canvas.ident, canvas);
} }
canvases = canvasMap;
console.log('Successfully fetched canvas data from pixelplanet'); console.log('Successfully fetched canvas data from pixelplanet');
} catch (e) { } catch (e) {
console.log('Couldn\'t connect to pixelplanet, trying to connect again in 60s'); console.log('Couldn\'t connect to pixelplanet, trying to connect again in 60s');
@ -33,4 +33,4 @@ function fetchCanvasData() {
} }
fetchCanvasData(); fetchCanvasData();
module.exports = canvases; export default canvases;

View File

@ -1,7 +1,5 @@
module.exports = { export const WIDTH = 1024;
WIDTH: 1024; export const HEIGHT = 768;
HEIGHT: 768; export const MAX_SCALE = 40; // 52 in log2
MAX_SCALE: 40; // 52 in log2 export const TILE_SIZE = 256;
TILE_SIZE: 256; export const TILE_ZOOM_LEVEL = 4;
TILE_ZOOM_LEVEL: 4;
}

View File

@ -1,11 +1,12 @@
import fetch from 'node-fetch'; import fetch from 'node-fetch';
const canvases = require('./canvases'); import canvases from './canvases.js';
const renderCanvas = require('./renderCanvas'); import renderCanvas from './renderCanvas.js';
const linkRegExp = /(#[a-z]*,-?[0-9]*,-?[0-9]*(,-?[0-9]+)?)/gi; const linkRegExp = /(#[a-z]*,-?[0-9]*,-?[0-9]*(,-?[0-9]+)?)/gi;
const linkRegExpFilter = (val, ind) => ((ind % 3) !== 2); const linkRegExpFilter = (val, ind) => ((ind % 3) !== 2);
let lastCoords = []; let lastCoords = [];
let lastParse = Date.now();
function compArray(arr1, arr2) { function compArray(arr1, arr2) {
for (let i = 0; i <= arr1.length; i += 1) { for (let i = 0; i <= arr1.length; i += 1) {
@ -16,7 +17,7 @@ function compArray(arr1, arr2) {
return true; return true;
} }
async function parseCanvasLinks(text) { export async function parseCanvasLinks(text) {
if (!text || !canvases) { if (!text || !canvases) {
return null; return null;
@ -28,9 +29,13 @@ async function parseCanvasLinks(text) {
} }
const coordsParts = msgArray[1].substr(1).split(','); const coordsParts = msgArray[1].substr(1).split(',');
if (compArray(coordsParts, lastCoords)) { const curTime = Date.now();
if (compArray(coordsParts, lastCoords)
|| curTime - 4000 < lastParse
) {
return null; return null;
} }
lastParse = curTime;
lastCoords = coordsParts; lastCoords = coordsParts;
const [ canvasIdent, x, y, z ] = coordsParts; const [ canvasIdent, x, y, z ] = coordsParts;
@ -40,9 +45,7 @@ async function parseCanvasLinks(text) {
} }
console.log(`Fetch canvas ${canvas.title} on ${x}/${y} with zoom ${z}`); console.log(`Fetch canvas ${canvas.title} on ${x}/${y} with zoom ${z}`);
const image = await renderCanvas(canvas, x, y, z); const imageData = await renderCanvas(canvas, x, y, z);
return image; return imageData;
} }
exports.parseCanvasLinks = parseCanvasLinks;

View File

@ -1,14 +1,15 @@
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import nodeCanvas from 'canvas';
const { const {
createCanvas, createCanvas,
loadImage, loadImage,
createImageData, createImageData,
} = require('canvas'); } = nodeCanvas;
const { import {
TILE_SIZE, TILE_SIZE,
} = require('./constants'); } from './constants.js';
async function fetchBaseChunk( async function fetchBaseChunk(
canvasId, canvasId,
@ -44,7 +45,7 @@ async function fetchTile(canvasId, zoom, cx, cy, tile) {
ctx.drawImage(image, 0, 0); ctx.drawImage(image, 0, 0);
} }
module.exports = function ( export default async function (
canvas, canvas,
zoom, zoom,
cx, cx,

View File

@ -1,14 +1,15 @@
const { createCanvas } = require('canvas'); import nodeCanvas from 'canvas';
const { createCanvas } = nodeCanvas;
const getChunk = require('./loadChunk'); import getChunk from './loadChunk.js';
const { import {
WIDTH, WIDTH,
HEIGHT, HEIGHT,
MAX_SCALE, MAX_SCALE,
TILE_SIZE, TILE_SIZE,
TILE_ZOOM_LEVEL, TILE_ZOOM_LEVEL,
} = require('./constants'); } from './constants.js';
function coordToChunk(z, canvasSize, tiledScale) { function coordToChunk(z, canvasSize, tiledScale) {
return Math.floor((z + canvasSize / 2) / TILE_SIZE * tiledScale); return Math.floor((z + canvasSize / 2) / TILE_SIZE * tiledScale);
@ -89,5 +90,14 @@ export default async function renderCanvas(
} }
await Promise.all(promises); await Promise.all(promises);
return can.toBuffer('image/png'); const memetype = 'image/png';
const imageBuffer = can.toBuffer(memetype);
return {
image: imageBuffer,
name: `ppfun-snap-${canvas.title}_${x}_${y}_${z}.png`,
type: memetype,
w: can.width,
h: can.height,
size: imageBuffer.size,
}
} }

View File

@ -1,9 +1,9 @@
"use strict"; "use strict";
const MatrixBridge = require("matrix-appservice-bridge").Bridge; import { Bridge } from 'matrix-appservice-bridge';
const PPfunSocket = require('./ppfunsocket'); import PPfunSocket from './ppfunsocket.js';
//const parseCanvasLinks = require('./pixelplanet') import { parseCanvasLinks } from './pixelplanet/index.js';
class PPfunMatrixBridge { class PPfunMatrixBridge {
constructor(opts) { constructor(opts) {
@ -28,7 +28,7 @@ class PPfunMatrixBridge {
apiSocketUrl, apiSocketUrl,
apiSocketKey, apiSocketKey,
); );
this.matrixBridge = new MatrixBridge({ this.matrixBridge = new Bridge({
homeserverUrl, homeserverUrl,
domain, domain,
registration, registration,
@ -79,6 +79,37 @@ class PPfunMatrixBridge {
); );
} }
async sendCanvasSnapshotIfNeccessary(roomId, msg) {
// post image if canvas link got posted
try {
const imageData = await parseCanvasLinks(msg);
if (imageData) {
const { image, name, type, h, w, size } = imageData;
const intent = this.matrixBridge.getIntent();
let mxcUrl;
mxcUrl = await intent.uploadContent(image, {
name,
type,
});
if (mxcUrl) {
intent.sendMessage(roomId, {
body: name,
msgtype: 'm.image',
url: mxcUrl,
info: {
h,
w,
mimetype: type,
size,
},
});
}
}
} catch (e) {
console.error(`Error when parsing pixelplanet url ${e}`);
}
}
async recMatrix(request, context) { async recMatrix(request, context) {
const event = request.getData(); const event = request.getData();
if (event.type === "m.room.message" if (event.type === "m.room.message"
@ -89,6 +120,8 @@ class PPfunMatrixBridge {
if (!cid) { if (!cid) {
return; return;
} }
const msg = event.content.body;
this.sendCanvasSnapshotIfNeccessary(event.room_id, msg);
const userId = event.sender; const userId = event.sender;
const uid = (userId.startsWith(`@${this.prefix}_`) const uid = (userId.startsWith(`@${this.prefix}_`)
&& userId.endsWith(this.domain)) && userId.endsWith(this.domain))
@ -102,7 +135,6 @@ class PPfunMatrixBridge {
this.idToNameMap.set(userId, userId.substring(1)); this.idToNameMap.set(userId, userId.substring(1));
name = await this.getDisplayName(userId); name = await this.getDisplayName(userId);
} }
const msg = event.content.body;
console.log(`MATRIX ${name}: ${msg}`); console.log(`MATRIX ${name}: ${msg}`);
this.sendPPfun(name, parseInt(uid, 10), msg, cid); this.sendPPfun(name, parseInt(uid, 10), msg, cid);
return; return;
@ -222,4 +254,4 @@ class PPfunMatrixBridge {
} }
} }
module.exports = PPfunMatrixBridge; export default PPfunMatrixBridge;

View File

@ -1,7 +1,7 @@
"use strict"; "use strict";
const EventEmitter = require('events'); import EventEmitter from 'events';
const WebSocket = require('ws') import WebSocket from 'ws';
class PPfunSocket extends EventEmitter { class PPfunSocket extends EventEmitter {
constructor(url, apisocketkey) { constructor(url, apisocketkey) {
@ -136,4 +136,4 @@ class PPfunSocket extends EventEmitter {
} }
} }
module.exports = PPfunSocket; export default PPfunSocket;