Skip to content

Instantly share code, notes, and snippets.

@mauris
Created November 15, 2016 14:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mauris/4c4676b3910dff1fef6a7fbe6a0c5e9a to your computer and use it in GitHub Desktop.
Save mauris/4c4676b3910dff1fef6a7fbe6a0c5e9a to your computer and use it in GitHub Desktop.
Submission
/**
* This code wasextracted from College Laundry Bot's admin panel.
* This server API route provides a long polling check on the authentication status.
* User needs to send a one-time password (provided on the admin panel) to the Telegram bot.
* The bot validates, and sets approval on the user's request. The admin panel on the other hand
* would periodically long-poll on the status of the approval. Once approved, a JsonWebToken given
* to user.
*/
router.post('/check', (req, res, next) => {
var username = req.body.username;
var code = req.body.code;
var pollTimer = null;
var retryCount = 0;
var checkAuth = () => {
++retryCount;
if (retryCount > 5) {
pollTimer = clearInterval(pollTimer);
return res.status(401).json({"error": "Authentication failed"});
}
exchangeCodeForTokenWhenApprovedPromise(username, code)
.then((result) => {
pollTimer = clearInterval(pollTimer);
res.json({ "status": "ok", role: result.admin.groupRole, token: result.token });
})
.catch((err) => {});
};
pollTimer = setInterval(checkAuth, 2500);
checkAuth();
});
/**
* This code was extracted from https://github.com/mauris/gitguard/blob/master/src/components/FileTree/index.js
* Using AngularJS, this 60-LoC file forms the controller neccessary for the frontend of a file tree component
* to be working.
*
* Whenever a folder from the list is selected, the code will request the server for the list of files in that path.
*/
const app = require('../../app');
let $controller = function ($http, $scope) {
let $ctrl = this;
$scope.path = [];
$scope.files = [];
$scope.isLoading = false;
let domain = $ctrl.domain;
let user = $ctrl.user;
let repo = $ctrl.repo;
let browsePath = () => {
$scope.isLoading = true;
$http.get('/api/repository/browse', { params: { domain: domain, user: user, repo: repo, path: '/' + $scope.path.join('/') } })
.then((res) => {
$scope.isLoading = false;
$scope.files = res.data.result;
});
};
$scope.$on('filetree.loadpath', (e, path) => {
$scope.path = path;
browsePath();
});
$scope.goUpFolder = () => {
if ($scope.path.length === 0) {
return;
}
$scope.path.pop();
browsePath();
};
$scope.open = (file) => {
if (file.isFile) {
$scope.$emit('filetree.open.file', { file: file, path: $scope.path.concat([file.name]) });
return;
}
$scope.openFolder(file.name);
$scope.$emit('filetree.open.folder', $scope.path);
};
$scope.openFolder = (folderName) => {
$scope.path.push(folderName);
browsePath();
};
browsePath();
};
app.component('fileTree', {
templateUrl: '/assets/views/FileTree/view.html',
controller: $controller,
bindings: {
domain: '=',
user: '=',
repo: '='
}
});
/**
* Code was extracted from https://github.com/sean-js/sean-web/blob/master/gulp/bower.js
* Gulp provides build automation and this script will build all frontend dependencies from bower
* into the web app public folder (which can be deleted and re-generated from source using Gulp).
*
* I do not need to care whether the CSS of the dependency is written in Sass or Less, the build
* automation script takes care of it.
* JavaScript and CSS are also uglified (compacted + minified) for production towards the end. If
* the environment is in development, sourcemaps are also produced so that the code can be seen in
* the browser's inspector tool.
*/
var gulp = require('gulp');
var $ = require('gulp-load-plugins')({
pattern : ['gulp-*', 'main-bower-files', 'del'],
camelize: true
});
/**
* Code performs gulp building from the bower_components folder.
* For all Less, Sass and CSS files, they are first compiled/copied into a
* temp directory before being concatenated into a single CSS file
* @exports null
*/
(() => {
'use strict';
/*
* Compile Less files from bower components into CSS in the temp directory
*/
gulp.task('bower-less', () => {
return gulp.src($.mainBowerFiles())
.pipe($.filter("**/*.less"))
.pipe($.less())
.pipe(gulp.dest('.tmp/'));
});
/*
* Compile Sass files from bower components into CSS in the temp directory
*/
gulp.task('bower-sass', () => {
return gulp.src($.mainBowerFiles())
.pipe($.filter("**/*.scss"))
.pipe($.sass())
.pipe(gulp.dest('.tmp/'));
});
/*
* Copy font files from bower components folder into the public assets folder
*/
gulp.task('bower-fonts', () => {
return gulp.src(
[
"bower_components/*/{font,fonts}/*",
]
)
.pipe($.flatten())
.pipe($.filter('**/*.{eot,svg,ttf,woff,woff2}'))
.pipe(gulp.dest("public/assets/fonts"));
});
/*
* Copy CSS files from bower components folder into the temp directory
*/
gulp.task('bower-css', () => {
return gulp.src($.mainBowerFiles())
.pipe($.filter('**/*.css'))
.pipe($.flatten())
.pipe(gulp.dest('.tmp'));
});
/*
* concatenate all CSS files in the temp directory, clean them and copy
* them into the public assets folder
*/
gulp.task('bower-stylesheets', ['bower-less', 'bower-sass', 'bower-css'], () => {
return gulp.src(
[
".tmp/*.css"
]
)
.pipe($.concat('vendor.css'))
.pipe($.replace('../font/', '../fonts/'))
.pipe($.cleanCss())
.pipe(gulp.dest("public/assets/css"));
});
/*
* Process all bower components JS files into public assets folder as
* vendor.js
*/
gulp.task('bower-js', () => {
var jsFilter = $.filter('**/*.js');
return gulp.src($.mainBowerFiles())
.pipe(jsFilter)
.pipe($.if(process.env.NODE_ENV === 'development', $.sourcemaps.init({loadMaps: true})))
.pipe($.concat('vendor.js'))
.pipe($.uglify())
.pipe($.if(process.env.NODE_ENV === 'development', $.sourcemaps.write('./')))
.pipe(gulp.dest('public/assets/js'));
});
/*
* Process bower JS, CSS and font resources
*/
gulp.task('bower', ['bower-js', 'bower-stylesheets', 'bower-fonts']);
})();
/**
* This code was extracted from https://github.com/mauris/utown-queue-bot/blob/master/src/callbacks/join.js
* These two functions are interesting: createTicketAndGroup creates both a ticket and group in a single command.
* while createTicket only creates a ticket. Since these operations needs to be executed atomically, a
* DBMS transaction needs to be created and all operations must execute within the context of the transactions.
*
* However, the functions took care of whether or not transactions have been created or not, if the function was
* called without a transaction context, it will create one for itself.
* This allows createTicketAndGroup to re-use createTicket easily and passing the transaction context down to it.
*/
let createTicket = (numberOfPeople, _user, _event, group, transaction) => {
if (!transaction) {
return models.sequelize
.transaction((t) => {
return createTicket(numberOfPeople, _user, _event, group, t);
});
}
var promises = [];
promises.push(
models.Ticket
.create(
{
"userId": _user.userId,
"eventId": _event.eventId,
"groupId": group ? group.groupId : null,
"datetimeStart": group ? models.sequelize.fn("NOW") : null,
"noOfPeople": numberOfPeople
},
{ transaction: transaction }
)
);
promises.push(
_user
.update(
{
"isInQueue": true
},
{ transaction: transaction }
)
);
return Promise.all(promises);
};
let createTicketAndGroup = (numberOfPeople, _user, _event, transaction) => {
if (!transaction) {
return models.sequelize
.transaction((t) => {
return createTicketAndGroup(numberOfPeople, _user, _event, t);
});
}
return models.Group
.create(
{
eventId: _event.eventId,
totalNoOfPeople: numberOfPeople
},
{ transaction: transaction }
)
.then((group) => {
return createTicket(numberOfPeople, _user, _event, group, transaction);
});
}
/**
* This code was extracted from https://github.com/mauris/cs2103-pr-bot/blob/master/src/seedu.js
* The underlying library Accuser uses function chaining so that an instance of new worker can be defined
* using method chaining. In some cases, like how jQuery uses it, it can allow the developer to read the
* chain English-alike.
*/
var utility = require('../utility');
module.exports = function(accuser, repoName) {
var repo = accuser.addRepository('se-edu', repoName);
repo.newWorker()
.filter(function(repository, issue){
// ensure that we only work with PRs that do not have an assignee
return issue.pull_request;
})
.do(function(repository, issue) {
console.log("Looking at se-edu PR #" + issue.number);
var result = utility._titleRegex.exec(issue.title);
if (result === null) {
return;
}
console.log("Commenting and closing se-edu " + repoName + " PR #" + issue.number);
accuser.comment(repository, issue, "This PR should be against a repo in the org [nus-cs2103-AY1617S1](https://github.com/nus-cs2103-AY1617S1), "
+ "not against the repo in se-edu org :-)\n\nClosing ..."
+ "\n\nNote: this comment is posted by a bot. If you believe this is done in error, please"
+ " create an issue at [cs2103-pr-bot](https://github.com/mauris/cs2103-pr-bot/issues) and add a link to this PR.");
accuser.close(repository, issue);
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment