diff --git a/.gitignore b/.gitignore
index 722d5e7..f64d2da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
.vscode
+main
+pdwebconfig.toml
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c8708ae
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+run:
+ ${MAKE} -j2 backgroundrun backgroundts
+build:
+ tsc res/static/res/typescript/lib/*.ts --outFile res/static/res/script/pixellib.js \
+ res/static/res/typescript/home/*.ts \
+ res/static/res/typescript/lib/*.ts --outFile res/static/res/script/home.js
+ go build main.go -o pixeldrain-web
+
+deps:
+ npm install -g typescript
+
+backgroundrun:
+ go run main.go
+backgroundts:
+ tsc --watch --project res/static/res/typescript/home
+ --project res/static/res/typescript/textupload
diff --git a/blackchancery.zip b/blackchancery.zip
deleted file mode 100644
index 58da515..0000000
Binary files a/blackchancery.zip and /dev/null differ
diff --git a/conf/config.go b/conf/config.go
index 67cdf20..2f7e403 100644
--- a/conf/config.go
+++ b/conf/config.go
@@ -64,6 +64,12 @@ func Init() {
log.Info("├%21s: %v", v, vi.Get(v))
}
}
+
+ if DebugMode() {
+ log.SetLogLevel(4)
+ } else {
+ log.SetLogLevel(3)
+ }
}
func writeCfg() {
diff --git a/main b/main
deleted file mode 100755
index 49bb8b5..0000000
Binary files a/main and /dev/null differ
diff --git a/pixelapi/list.go b/pixelapi/list.go
index a5f337b..c1bc715 100644
--- a/pixelapi/list.go
+++ b/pixelapi/list.go
@@ -4,11 +4,17 @@ import (
"encoding/json"
"fornaxian.com/pixeldrain-web/conf"
- "fornaxian.com/pixeldrain-web/log"
+)
+
+// API error constants
+const (
+ ListNotFoundError = "list_not_found"
)
// List information object from the pixeldrain API
type List struct {
+ Error *ErrorResponse
+ Success bool `json:"success"`
ID string `json:"id"`
Title string `json:"title"`
DateCreated int64 `json:"date_created"`
@@ -26,19 +32,24 @@ type ListFile struct {
ListDescription string `json:"list_description"`
}
-// GetList get a List from the pixeldrain API
+// GetList get a List from the pixeldrain API. Errors will be available through
+// List.Error. Standard error checks apply.
func GetList(id string) *List {
+ var list = &List{}
body, err := getString(conf.ApiUrlInternal() + "/list/" + id)
+ if err != nil {
+ list.Error = errorResponseFromError(err)
+ return list
+ }
+ err = json.Unmarshal([]byte(body), list)
if err != nil {
- log.Error("req failed: %v", err)
- return nil
+ list.Error = errorResponseFromError(err)
+ return list
}
- var list List
- err = json.Unmarshal([]byte(body), &list)
- if err != nil {
- log.Error("unmarshal failed: %v. json: %s", err, body)
- return nil
+
+ if !list.Success {
+ list.Error = errorResponseFromJSON(body)
}
- return &list
+ return list
}
diff --git a/pixelapi/request.go b/pixelapi/request.go
index 954cf17..a5486a2 100644
--- a/pixelapi/request.go
+++ b/pixelapi/request.go
@@ -1,8 +1,37 @@
package pixelapi
-import "net/http"
-import "io/ioutil"
-import "io"
+import (
+ "encoding/json"
+ "io"
+ "io/ioutil"
+ "net/http"
+)
+
+type ErrorResponse struct {
+ ReqError bool
+ Success bool `json:"success"`
+ Value string `json:"value"`
+ Message *string `json:"message"`
+ ID *string `json:"id"`
+}
+
+func errorResponseFromJSON(j string) *ErrorResponse {
+ var r = &ErrorResponse{}
+ var err = json.Unmarshal([]byte(j), r)
+ if err != nil {
+ r.Success = false
+ r.ReqError = true
+ r.Value = err.Error()
+ }
+ return r
+}
+func errorResponseFromError(e error) *ErrorResponse {
+ var r = &ErrorResponse{}
+ r.Success = false
+ r.ReqError = true
+ r.Value = e.Error()
+ return r
+}
func getString(url string) (string, error) {
req, err := http.NewRequest("GET", url, nil)
diff --git a/res/static/res/script/Bubbles.js b/res/static/res/script/Bubbles.js
deleted file mode 100644
index 487b67c..0000000
--- a/res/static/res/script/Bubbles.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Beforehand i'd like to tell you to not forget to add a width and height attribute to the canvas element, this can be styled with css for the prettyness, but to keep the responsiveness a width of 800 is nice with a height of 640 (if you want it to be a landscape styled right now, in any case a rectangle (not a squire) should be have 1 of the 2 attributes 4/5 like 80/100 or 640/800*/
-
-/* Global variables */
-var lastUpdate = Date.now();
-var myInterval = setInterval(tick, 16.333333333);
-var config = {
- images: {
- width: 40, /* The size the image will be scaled to, dont see this as a must, but as a nicer way because you can remove this if you also remove the 2 parameters from the render function */
- height: 60,
- },
- speed: {
- x: 5.6, /* A lil tricky because here we define the speed it travels with, but this can be either negative or postive value, so we determine possibility that on the image creation, by adding a * -1 or * 1 ;3 */
- y: 7 /* Just the speed it travels with vertically, not as tricky as the "x" value */
- }
-};
-
-/* Load in items trough ajax call (in case you keep em in a database, if not you can use it like this as well */
-
-var img_format = '.png'; /* Use the format you desire */
-var items = {
- add: function (img_source) {
- var img = new Image();
- img.src = 'img_' + this.length + img_format;
-
- e.direction = Math.random() < 0.5 ? 1 : -1; /* This is used to know if it's going left or right */
- e.curX = Math.random() * canvas.width();
- e.curY = canvas.height();
- this.push(img);
- }
-}
-
-items.add('your_image_path_plus_name');
-/*_________*/
-
-/* The preffered way */
-var items = {};
-$.ajax({
- url: 'your_api_call',
- success: function (response) {
- if (typeof {response: 1}) {
- response.forEach(function (element, index, array) {
- items.push(element);
- });
-
- items.forEach(function (e, i, a) {
- e.direction = Math.random() < 0.5 ? 1 : -1; /* This is used to know if it's going left or right */
- e.curX = Math.random() * canvas.width();
- e.curY = canvas.height();
- });
- }
- }
-});
-
-if (items.length === 0) {
- console.log(items); /* In possible debug scenario that something went wrong with the add function */
- console.log('Perhaps you did something wrong with the add functionality therefor no items are being found');
-}
-
-/* Lets get the loop going */
-items.forEach(function (e, i, a) { /* You should know by now that e == element, i == index, a == array
- e.start_location = Math.random() * canvas.width(); /* This will add its starter location, this could also be defined in either the image loop or the ajax call, but im lazy and i will not write this shit twice */
-});
-
-/* The simplest of simple looping skills */
-function tick() {
- var now = Date.now();
- var dt = now - lastUpdate;
- lastUpdate = now;
-
- update(dt);
- render();
-}
-
-function update(dt) {
- /* If game loop does not work, which i guess, take a look at "http://goo.gl/f8sQRD" */
- items.forEach(function (e, i, a) {
- e.curX += config.speed.x;
- e.curY += config.speed.y;
-
- /* Simple reset the shitty image */
- if ((e.curX > canvas.width()) || (e.curX + config.images.width < 0)) {
- e.curX = Math.random() * canvas.width();
- e.curY = canvas.height();
- }
- });
-}
-
-function render() {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- /* Render the images based on the updated data in the function "update()" */
- items.forEach(function (e, i, a) {
- ctx.drawImage(e, e.curX + config.speed.x * e.direction, e.curY - config.speed.y, config.image.width, config.images.height); /* this can be either said in update() or in render(), i prefer render, because i allways want to do the moving after the update, which verifies the speed and such please use "http://goo.gl/2HQbFy" for more information*/
- });
- /* get fucked nooblord, just go on with yer life why are you even looking at this if you're not the dev */
-}
\ No newline at end of file
diff --git a/res/static/res/script/Cookie.js b/res/static/res/script/Cookie.js
deleted file mode 100644
index d5b6d92..0000000
--- a/res/static/res/script/Cookie.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/*\
-|*|
-|*| :: cookies.js ::
-|*|
-|*| A complete cookies reader/writer framework with full unicode support.
-|*|
-|*| Revision #3 - July 13th, 2017
-|*|
-|*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
-|*| https://developer.mozilla.org/User:fusionchess
-|*| https://github.com/madmurphy/cookies.js
-|*|
-|*| This framework is released under the GNU Public License, version 3 or later.
-|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
-|*|
-|*| Syntaxes:
-|*|
-|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
-|*| * docCookies.getItem(name)
-|*| * docCookies.removeItem(name[, path[, domain]])
-|*| * docCookies.hasItem(name)
-|*| * docCookies.keys()
-|*|
-\*/
-
-var Cookie = {
- get: function (sKey) {
- if (!sKey) { return null; }
- return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
- },
- set: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
- if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
- var sExpires = "";
- if (vEnd) {
- switch (vEnd.constructor) {
- case Number:
- sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
- /*
- Note: Despite officially defined in RFC 6265, the use of `max-age` is not compatible with any
- version of Internet Explorer, Edge and some mobile browsers. Therefore passing a number to
- the end parameter might not work as expected. A possible solution might be to convert the the
- relative time to an absolute time. For instance, replacing the previous line with:
- */
- /*
- sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; expires=" + (new Date(vEnd * 1e3 + Date.now())).toUTCString();
- */
- break;
- case String:
- sExpires = "; expires=" + vEnd;
- break;
- case Date:
- sExpires = "; expires=" + vEnd.toUTCString();
- break;
- }
- }
- document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
- return true;
- },
- remove: function (sKey, sPath, sDomain) {
- if (!this.hasItem(sKey)) { return false; }
- document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
- return true;
- },
- has: function (sKey) {
- if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
- return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
- },
- keys: function () {
- var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
- for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
- return aKeys;
- }
-};
\ No newline at end of file
diff --git a/res/static/res/script/compiled/README b/res/static/res/script/compiled/README
new file mode 100644
index 0000000..e1286db
--- /dev/null
+++ b/res/static/res/script/compiled/README
@@ -0,0 +1,4 @@
+All files in this directory are compiled typescript files. You can find the
+sources in /res/typescript.
+
+Have fun typing!
\ No newline at end of file
diff --git a/res/static/res/script/compiled/home.js b/res/static/res/script/compiled/home.js
new file mode 100644
index 0000000..38f959d
--- /dev/null
+++ b/res/static/res/script/compiled/home.js
@@ -0,0 +1,215 @@
+var uploader = null;
+var finishedUploads = new Array();
+var totalUploads = 0;
+var UploadProgressBar = /** @class */ (function () {
+ function UploadProgressBar(file) {
+ this.file = file;
+ this.name = file.name;
+ this.queueNum = totalUploads;
+ totalUploads++;
+ this.uploadDiv = document.createElement("a");
+ this.uploadDiv.setAttribute("class", "file_button");
+ this.uploadDiv.innerText = "Queued\n" + this.file.name;
+ this.uploadDivJQ = $(this.uploadDiv);
+ $("#uploads_queue").append(this.uploadDivJQ.hide().fadeIn('slow'));
+ }
+ UploadProgressBar.prototype.onProgress = function (progress) {
+ this.uploadDiv.innerText = "Uploading... " + Math.round(progress * 1000) / 10 + "%\n" + this.file.name;
+ this.uploadDiv.setAttribute('style', 'background: linear-gradient('
+ + 'to right, '
+ + '#111 0%, '
+ + 'var(--highlight_color) ' + ((progress * 100)) + '%, '
+ + '#111 ' + ((progress * 100) + 1) + '%)');
+ };
+ UploadProgressBar.prototype.onFinished = function (id) {
+ finishedUploads[this.queueNum] = id;
+ this.uploadDiv.setAttribute('style', 'background: #111');
+ this.uploadDiv.setAttribute('href', '/u/' + id);
+ this.uploadDiv.setAttribute("target", "_blank");
+ this.uploadDivJQ.html(''
+ + this.file.name + '
'
+ + '' + window.location.hostname + '/u/' + id + '');
+ };
+ UploadProgressBar.prototype.onFailure = function (response, error) {
+ this.uploadDiv.setAttribute('style', 'background: #821C40');
+ this.uploadDivJQ.html(this.file.name + '
'
+ + 'Upload failed after three tries!');
+ };
+ return UploadProgressBar;
+}());
+function handleUploads(files) {
+ if (uploader === null) {
+ uploader = new UploadManager();
+ $("#uploads_queue").animate({ "height": "340px" }, { "duration": 2000, queue: false });
+ }
+ for (var i = 0; i < files.length; i++) {
+ uploader.uploadFile(new UploadProgressBar(files.item(i)));
+ }
+}
+/*
+ * Form upload handlers
+ */
+// Relay click event to hidden file field
+$("#select_file_button").click(function () { $("#file_input_field").click(); });
+$("#file_input_field").change(function (evt) {
+ handleUploads(evt.target.files);
+ // This resets the file input field
+ // http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
+ $('#file_name').html("");
+ $("#file_upload_button").css("visibility", "hidden");
+ $("#file_input_field").wrap("