[ANN] Joke - A Joke Twitter Bot

by Andrew Chilton


Posted 19 days ago in category apps.


A joke Twitter bot. To be honest, it's not really a joke, so perhaps a Twitter Bot about Jokes is a better description.


Tags: twitter, bot.


[ANN] Flash - A Simple Game

by Andrew Chilton


Posted 3 months ago in category apps.


Firstly, I'd like to announce a new app called Flash. As is customary, here are all the links you need for this app:

Now that you have all the links, feel free to view the source code, or remix it yourself so you can use it and follow along.

About

In the main Glitch editor, you are able to upload any binary files to your assets as you see fit (up to 512MB worth as specified in the FAQ). Of course this means you can also upload images too and display them from within your pages.

Once I'd seen this I decided that I wanted to make a FlashCard game for my 4 year old based on all of the Thomas and Friends characters. He already knows 98% of them but I thought we could also have some fun trying to spell them as well as finding those characters on the keyboard.

Hence the flash-thomas game was born : https://flash-thomas.glitchapps.org/

Of course, making a small skeleton app in Glitch is (as always) my aim so that you can also remix it and either change it or upload your own images, the links for which you can see above.

Aims

The main aim I wanted to try here was creating a package to help you with parsing your .glitch-assets file, and the ability to map an answer back to a UUID contained in that file.

For parsing the .glitch-assets file, I created a new package (now on npm) called glitch-assets which you can now use from within your own Glitches:

As for mapping the answers back to these assets, well, that's just a plain JSON file read from and written to by the app itself. Nothing overly interesting there in the end.

I hope you have fun playing the game. Feel free to remix, update, improve, fix bugs, or do whatever you like and please let me know so I can see what you did. Many thanks.


Tags: game, assets.


The .data dir and the Editor

by Andrew Chilton


Posted 4 months ago in category platform.


Whilst writing a short FAQ for Glitch (yet to be released, but watch this space) I started writing an entry for the following question.

Why do files created in .data/ disappear from the editor?

My answer in the FAQ is going to be the following:

In short they don't disappear completely, they only disappear from the editor view. This happens after your app sleeps.

However this isn't the whole story since I ended up going down a rabbit hole to figure out more of how the .data dir and the editor interact. Here's what I found.

In general the editor shows the files in the editor that Git knows about on the server. If you'd like to see this then open your console (in 'Advanced Settings') and run the following command (this is the current state of this ga-faq project):

$ git ls-files
.config/configstore/update-notifier-npm.json
.glitch-assets
License.md
ReadMe.md
lib/app.js
lib/faqs.js
package.json
public/s/css/styles.css
public/s/js/app.js
server.js
views/index.pug

However the .data dir is ignored by Git due to configuration set up by Glitch. We can see this by doing the following on the server:

app@ga-faq:~ 21:01 
$ touch .data/new.txt
app@ga-faq:~ 21:03 
$ git add .data/new.txt 
The following paths are ignored by one of your .gitignore files:
.data/new.txt
Use -f if you really want to add them.

Righto, we'll try that.

app@ga-faq:~ 21:04 
$ git add -f .data/new.txt 
app@ga-faq:~ 21:06 
$ git ls-files | grep new
.data/new.txt

That seems to work, but the new.txt file doesn't yet show up in your editor. Since this isn't automatic yet, you can force the editor to refresh the app list by running the following:

$ refresh

$ git ls-files | grep new
.data/new.txt

Bah! Even though we've added that file to git, and git still knows about it, the file doesn't appear in the editor. This seems to be something which Glitch has strong opinions on, which is fine, since the .data/ dir isn't copied when you remix a project so this seems like the safest option.

Let's tidy-up by telling git to unstage this new file:

$ git reset HEAD .data/new.txt

Now we've tried this by adding a file to git on the server, so let's try it in the editor too. Go and click + New File and type in .data/another.txt. Bam, we can see it in the editor.

In this case, neither git ls-files nor git status knows about the file, however it is showing up in the editor. This is a good indicator of the answer to our original question.

Since you added the file in the editor then it knows to show you it in that current session. However, the next time your app sleeps and your editor either loads or reloads then the file will disappear from the editor view, because git doesn't know about it.

But don't fret, since that file still exists on the server, which you can see with the following command:

$ ls -l .data/another.txt
-rw-r--r-- 1 app app 0 Dec 11 21:12 .data/another.txt

The upshot is, don't expect any files in .data/ to be copied upon remix (which we already knew) but also don't expect any files in there to be versioned with git either, and hence be shown in the editor in any meaningful way. However, do expect that any files in there will be persisted within your project space on the server under /app/.data as is expected.

One final thing I'd like to investigate is where the rule telling Git to ignore .data lives. Usually there is a .gitignore file at the top-level of the git repo:

app@ga-faq:~ 21:17 
$ pwd
/app
app@ga-faq:~ 21:17 
$ ls -l .gitignore
ls: cannot access '.gitignore': No such file or directory

Perhaps there is something in the .git/config which gives us an indication of where this rule might live:

app@ga-faq:~ 21:18 
$ cat .git/config 
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[user]
        email = none
        name = Glitch (ga-faq)

Nothing there either, so let's check the GIT_* environment variables. We can type echo $GIT and then press tab a couple of times for autocomplete:

app@ga-faq:~ 21:19 
$ echo $GIT<tab><tab>

After being stumped for a while, Tim Kington helped in pointing out that there is a global .gitignore file used in your Glitch project. Let's have a look:

$ git config --list | grep excludes
core.excludesfile=/etc/gitignore-global

Ace. We've got it. And it wouldn't be us if we didn't take a peek inside:

$ cat /etc/gitignore-global 
*.log
*.pid
*.pid.lock
*.pyc
*.seed
*.tgz
.bash_history
.bundle
.cache
.cargo
.data
.env
.eslintcache
.glitch-meta
.gomix-meta
.grunt
.local
.lock-wscript
.next
.node-gyp
.node_repl_history
.npm
.npmrc
.nuget
.nyc_output
.ssh
.subversion
.yarn-integrity
bower_components
build/Release
coverage
jspm_packages/
lib-cov
logs
node_modules/
npm-debug.log*
package-lock.json
pids
target
typings/
yarn-debug.log*
yarn-error.log*

And finally there we have it. The .data directory is there just as we expected. It was certainly the long way round to find this but I think we've had a good adventure doing it.


Tags: editor, data.


[ANN] Image Resize App on Glitch

by Andrew Chilton


Posted 5 months ago in category apps.


Firstly, I'd like to announce a new app called Image Resize. As is customary, here are all the links you need for this app:

Now that you have all the links, feel free to view the source code, or remix it yourself so you can use it and follow along.

About

The image-resize app allows you to simply scale an image by choosing a width, uploading an image, and saving the result. It works on images up to 50MB and with over 20,000 pixels in both dimensions. That's a whopping 400,000,000 pixels.

Aims

The main two things I wanted to try here were file uploads and resizing images.

For file uploads I used a package called multer. Though I've used it many times before but I just wanted to get a feel for file uploads on Glitch, like how long they take and where to save them.

And for resizing images, though I've used packages like imagemagick, gm (graphics magick), and used node's exec package to shell-out to other image manipulation programs, for this project I wanted to use sharp.

Uploading Files

Firstly, let's talk about using multer and how that fits into the Glitch environment. As we know we are able to use the .data/ directory to save files that do not appear in the Editor. So, to be honest (and this is my mistake), I actually used this dir to save the uploads.

Whilst this seemed okay at the time, just remember that your /app mount point is only allowed up to 128MB of storage as shown below.

$ df -kh
Filesystem      Size  Used Avail Use% Mounted on
/dev/rbd59      128M   24M   79M  23% /app

Also remember that the /app area (which includes the .data directory here : /app/.data/) is permanent and is very much a sacred area for the files you really don't want to lose. For temporary files such as those uploaded this area is both overkill and unecessary.

And, ahah, re-reading that last sentence gives us a clue. The uploaded files should be temporary, so let's have another look at one specific line from the output of the df command above:

$ df -kh
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       49G   22G   28G  44% /tmp

And there we have it. A whopping 28GB we can play with! We're onto a winner.

So firstly, let's set up multer to use this area for file uploads:

const multer = require('multer')

const tmpDir = '/tmp/image-resize'
const upload = multer({ dest: tmpDir })

In our form, we're going to have the following file input such that the uploaded file is in the field named image. Since we're POSTing the form to '/' then we want multer to do it's thing prior to our own route handler running. Let's try this:

app.post("/", upload.single('image'), (req, res, next) => {
  // .. our route handler ...
})

This means that multer parses the incoming file, stores the contents inside /tmp/image-resize and sets the file information in req.file (since we told it to only expect a single file, not multiple files). Inside the route handler, we can access the file info in req.file as mentioned and here is an example of that:

file: {
  fieldname: 'image',
  originalname: 'pexels-photo.jpg',
  encoding: '7bit',
  mimetype: 'image/jpeg',
  destination: '/tmp/image-resize',
  filename: 'c77969beaf061313863216dbdc86997a',
  path: '/tmp/image-resize/c77969beaf061313863216dbdc86997a',
  size: 2468354
}

Great! Now we can see where the file has been placed req.file.destination and named req.file.filename by multer. Or for the full path we use req.file.path. It is this that gives us the filename we can use for sharp to use.

Reszing the Image

Now that the (slightly complicated) uploading is done, the resize is actually quite simple, so we'll just get straight to it. Imagine we've checked that the width is a valid number and we'll talk about outfile a bit later. Essentially once we have an outfile we'll serve it back to the user:

  sharp(req.file.path)
    .rotate()
    .resize(width)
    .toFile(outfile)
    .then(() => {
      res.sendFile(outfile, (err) => {
        if (err) return next(err)
      })
    })

As you can see, I'm using the promise version of sharp rather than callbacks since it made it easier to cope with all (currently omited) error conditions. But wait, what does happen if there is an error. We'll check right here:

    .catch(err => {
      next(err) 
     })

One thing to note here is that multer doesn't automatically remove any files itself after the request has finished, let alone the new file we've just written, so let's deal with those. What about if we set a timer for 5s after the request has finished to delete them. This sounds reasonable such that the files don't hang around for long, but we don't delete them too early either.

However, let's just think about the anatomy of a request. We only enter our handler when multer has completely written the file to disk, so we want to set our time to delete that file as soon as we know the image manipulation has finished (either correctly, or it has failed). Let's see what this looks like in the error case (imagine someone has uploaded a file named text.jpg which is a misnamed text file):

    .catch(err => {
      setTimeout(() => {
        fs.unlink(filename, (err) => console.log)
      }, 5 * 1000)
      next(err) 
     })

Remember that we don't need to remove the new outfile if processing fails since nothing will have been written to it.

And finally, for the happy path we want to remove both the original and the new file, but because we know when we've finished with either we can remove them at different times, such as:

      res.sendFile(outfile, (err) => {
        setTimeout(() => {
          fs.unlink(filename, (err) => console.log)
        }, 5 * 1000)
        if (err) return next(err)
        console.log('Sent:', outfile)
        setTimeout(() => {
          fs.unlink(outfile, (err) => console.log)
        }, 5 * 1000)
      })

Here' we're setting up a timer to remove the original as soon as we no longer need it (whether the res.sendFile() was successful or not). And as soon as the res.sendFile() has finished successfully we'll remove the outfile too.

Apart from some sanity checking of the incoming width parameter, and making sure that we only accept image/png and image/jpeg (and setting the extension correctly), we're pretty much done.

I hope you've enjoyed this post. Please follow us on @GlitchApps and I'd love to hear your feedback.


Tags: images.


Hello, World!

by Andrew Chilton


Posted 5 months ago in category platform.


This is an example post that was added via the main Glitch Editing interface, and therefore is added to Git inside your project filespace.

Once you add you first post, feel free to delete both this hello-world.md file and the metadata associated with it in hello.world.json.

For more information follow our main blog at GlitchApps.org.

(Ends)


Tags: nodejs, blog.


« Older Posts - Page of 1 - Newer Posts »