Browse Source

Finalize main.py, Readme, and CSS/JS

main
Noëlle 1 year ago
parent
commit
de443e9bf6
No known key found for this signature in database

+ 9
- 0
.gitignore View File

@@ -1 +1,10 @@
config.ini
bin/*
include/*
lib/*
lib64/*
pyenv.cfg
lib64
pdfs/*
html/raw/*
pyvenv.cfg

+ 14
- 1
README.md View File

@@ -1,3 +1,16 @@
# pdf-grabber

For grabbing PDFs from ICRA 2022
For grabbing PDFs from ICRA 2022!

## Usage

Make sure you have Python 3.6 or later, install a [virtual environment](https://docs.python.org/3/library/venv.html) if you like, then run these in a command line:

* `pip3 install -r requirements.txt`
* `python3 main.py`

This script will create a sub-directory, `pdfs/`, where it will store the PDFs it downloads. PDFs are named according to the presentation's name and the PDF's file number.

You can use the `-e` flag (e.g. `python3 main.py -e 88`) to determine which event ID to scan for presentations that have PDFs. By default, this is event 88. (The number is unfortunate; it's the event this was written for, [the 39th IEEE International Conference on Robotics and Automation](https://events.infovaya.com/event?id=88), and bears no other symbolism here.)

You can use the `-s` flag (e.g. `python3 main.py -s`) to save the HTML content of each page along with the PDF. This is mostly for diagnostic purposes. The CSS and Javascript files required by the HTML files are included here, but you may have to move them somewhere else to get them to work properly (where depends on your system).

+ 5
- 0
html/css/bootstrap.min.css
File diff suppressed because it is too large
View File


+ 4
- 0
html/css/font-awesome.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
html/css/jquery.fancybox.css View File

@@ -0,0 +1 @@
/*!fancyBox v2.1.4 fancyapps.com | fancyapps.com/fancybox/#license*/.fancybox-wrap,.fancybox-skin,.fancybox-outer,.fancybox-inner,.fancybox-image,.fancybox-wrap iframe,.fancybox-wrap object,.fancybox-nav,.fancybox-nav span,.fancybox-tmp{padding:0;margin:0;border:0;outline:none;vertical-align:top}.fancybox-wrap{position:absolute;top:0;left:0;z-index:8020}.fancybox-skin{position:relative;background:#f9f9f9;color:#444;text-shadow:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fancybox-opened{z-index:8030}.fancybox-opened .fancybox-skin{-webkit-box-shadow:0 10px 25px rgba(0,0,0,.5);-moz-box-shadow:0 10px 25px rgba(0,0,0,.5);box-shadow:0 10px 25px rgba(0,0,0,.5)}.fancybox-outer,.fancybox-inner{position:relative}.fancybox-inner{overflow:hidden}.fancybox-type-iframe .fancybox-inner{-webkit-overflow-scrolling:touch}.fancybox-error{color:#444;font:14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;margin:0;padding:15px;white-space:nowrap}.fancybox-image,.fancybox-iframe{display:block;width:100%;height:100%}.fancybox-image{max-width:100%;max-height:100%}#fancybox-loading,.fancybox-close,.fancybox-prev span,.fancybox-next span{background-image:url(fancybox_sprite.png)}#fancybox-loading{position:fixed;top:50%;left:50%;margin-top:-22px;margin-left:-22px;background-position:0 -108px;opacity:.8;cursor:pointer;z-index:8060}#fancybox-loading div{width:44px;height:44px;background:url(fancybox_loading.gif) center center no-repeat}.fancybox-close{position:absolute;top:-18px;right:-18px;width:36px;height:36px;cursor:pointer;z-index:8040}.fancybox-nav{position:absolute;top:0;width:40%;height:100%;cursor:pointer;text-decoration:none;background:transparent url(blank.gif);-webkit-tap-highlight-color:transparent;z-index:8040}.fancybox-prev{left:0}.fancybox-next{right:0}.fancybox-nav span{position:absolute;top:50%;width:36px;height:34px;margin-top:-18px;cursor:pointer;z-index:8040;visibility:hidden}.fancybox-prev span{left:10px;background-position:0 -36px}.fancybox-next span{right:10px;background-position:0 -72px}.fancybox-nav:hover span{visibility:visible}.fancybox-tmp{position:absolute;top:-99999px;left:-99999px;visibility:hidden;max-width:99999px;max-height:99999px;overflow:visible!important}.fancybox-lock{overflow:hidden}.fancybox-overlay{position:absolute;top:0;left:0;overflow:hidden;display:none;z-index:8010;background:url(fancybox_overlay.png)}.fancybox-overlay-fixed{position:fixed;bottom:0;right:0}.fancybox-lock .fancybox-overlay{overflow:auto;overflow-y:scroll}.fancybox-title{visibility:hidden;font:normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;position:relative;text-shadow:none;z-index:8050}.fancybox-opened .fancybox-title{visibility:visible}.fancybox-title-float-wrap{position:absolute;bottom:0;right:50%;margin-bottom:-35px;z-index:8050;text-align:center}.fancybox-title-float-wrap .child{display:inline-block;margin-right:-100%;padding:2px 20px;background:0 0;background:rgba(0,0,0,.8);-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;text-shadow:0 1px 2px #222;color:#fff;font-weight:700;line-height:24px;white-space:nowrap}.fancybox-title-outside-wrap{position:relative;margin-top:10px;color:#fff}.fancybox-title-inside-wrap{padding-top:10px}.fancybox-title-over-wrap{position:absolute;bottom:0;left:0;color:#fff;padding:10px;background:#000;background:rgba(0,0,0,.8)}

+ 1
- 0
html/css/reset.css View File

@@ -0,0 +1 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:0 0}body{line-height:1}ol,ul{list-style:none}:focus{outline:0}ins{text-decoration:none}del{text-decoration:line-through}table{border-collapse:collapse;border-spacing:0}

+ 1
- 0
html/css/site.min.css
File diff suppressed because it is too large
View File


+ 6
- 0
html/js/bootstrap.min.js
File diff suppressed because it is too large
View File


+ 250
- 0
html/js/comments.js View File

@@ -0,0 +1,250 @@
var loading = false;

$(document).ready(function () {
// make alert button fixed and hide it after a few seconds
$(".alert.msg").addClass("fixed-alert");
setTimeout(function(){ $(".alert.msg").remove(); }, 5000);
// on show replies link click
$(".show-replies").click(function(e){

e.preventDefault();

// check if data is not still loading
if(loading == true) { return false; }

// store self into a var to give it access inside the post
var self = $(this);

// set loading to true and get data from html element attributres
loading = true;
data = $(this).data();

// make an ajax request to get comment replies
$.post("/ajax.php?action=commentReplies&commentId=" + castAsInteger(data.commentid), {})

// data retrieved. try and build the html
.done(function (payload) {

if(payload.error === true) {
// reset loading flag and throw error
loading = false;
throw new Error("Failed to parse ajax payload");
}

// loop data and build replies html
repliesHtml = "";
payload.data.comments.forEach(function(item){

// html data
const commentId = castAsInteger(item.id);
const repliedTo = (item.repliedToUser ? "<a href='/profile?id=" + item.repliedToUserId + "'>@" + item.repliedToUser + "</a> " : "" );
const likeBtnClass = item.hasLiked == 1 ? "class='active'" : "";
const dislikeBtnClass = item.hasDisliked == 1 ? "class='active'" : "";
const profileImg = item.profileImgUrl != false ? `<a href='/profile?id=${item.usersId}' class='comment-profile-image has-image' style='background-image: url(${item.profileImgUrl})'></a>` : `<a href='/profile?id=${item.usersId}' class='comment-profile-image'><i class='fa fa-user' aria-hidden='true'></i></a>`;

//delete form
deleteHtml = "";
if(payload.data.canDelete) {
deleteHtml = `
<form method='post' class='delete-comment' action='#comments'>
<input type='hidden' name='action' value='deleteComment' />
<input type='hidden' name='commentId' value='${commentId}' />
<button type='submit'><i class='fa fa-times' aria-hidden='true'></i></button>
</form>
`;
}

// build replis html (specific to comment type)
repliesHtml += `
<div id='commentRow${commentId}' class='comment-row'>
${deleteHtml}${profileImg}
<div class='comment-box'>
<p><a href='/profile?id=${item.usersId}'>${item.profileName}</a> &bull; ${item.datePosted}</p>
<p class='user-comment'>
${repliedTo}
${item.iv_comment}
</p>
</div>
<div class='score-button-wrapper'>
<div class='score-form like-form'>
<button type='submit' data-object='${data.objectid}' data-type='${item.commentType}' data-commentId='${commentId}' data-like='1' ${likeBtnClass}><i class='fa fa-thumbs-up' aria-hidden='true'></i></button>
<span class='likeCounter'>${item.totalLikes}</span>
</div>
<div class='score-form dislike-form'>
<button type='submit' data-object='${data.objectid}' data-type='${item.commentType}' data-commentId='${commentId}' data-like='0' ${dislikeBtnClass}><i class='fa fa-thumbs-down' aria-hidden='true'></i></button>
<span class='likeCounter'>${item.totalDislikes}</span>
</div>
<a href='#' class='reply reply-button' data-profile='${item.profileName}' data-object='${data.objectid}' data-type='${item.commentType}' data-parent='${item.parentId}' data-author='${item.usersId}' data-reply='${commentId}'>Reply</a>
</div>
</div>
<div id='replyBox${commentId}'></div>
`;
});

// set html and show replies
$('#replies'+ data.commentid).html(repliesHtml);

//check if comment box text is overflowing
limitReplyBoxHeight();

//bind click events
bindReplyButtons();
bindLikesButtons();

// remove link and reset loading
$(self).remove();
loading = false;
})
.fail(function(){

// reset loading flag
loading = false
return false;
})
;
});

//check if comment box text is overflowing max of 90 height
limitReplyBoxHeight();

//bind click events
bindReplyButtons();
bindLikesButtons();
});

function castAsInteger(number) { return isNaN(parseInt(number)) ? 0 : parseInt(number); }

function limitReplyBoxHeight() {

// check height of comment boxes
$('.comment-box').each(function () {
if ($(this).outerHeight() >= 125) {
$(this).addClass('comment-box-overflow');
}
});

// update box heights
bindHeightHandler();
}

// bind functions
function bindHeightHandler() {
$( ".comment-box-overflow").unbind( "click.show", toggleHeightHandler );
$( ".comment-box-overflow").bind( "click.show", toggleHeightHandler );
}

function bindCancelButtons() {
// bind cancel button
$( ".cancel-reply").unbind( "click.cancel", cancelhandler );
$( ".cancel-reply").bind( "click.cancel", cancelhandler );
}

function bindReplyButtons() {
// bind reply button
$( ".reply-button").unbind( "click.replys", replyhandler );
$( ".reply-button").bind( "click.replys", replyhandler );
}

function bindLikesButtons() {
$(".score-form button").unbind( "click.like", likesHandler );
$(".score-form button").bind( "click.like", likesHandler );
}

function escapeHtml(html){
var text = document.createTextNode(html);
var p = document.createElement('p');
p.appendChild(text);
return p.innerHTML;
}

// bind handlers
var toggleHeightHandler = function() {
$(this).toggleClass("show-overflow");
}

var cancelhandler = function(e) {

// prevent form submit
e.preventDefault();
replyboxId = $(this).data().replybox;

// reset reply box html
$("#replyBox" + replyboxId).html("");
}

var likesHandler = function(e) {

e.preventDefault();
data = $(this).data();

commentId = castAsInteger(data.commentid);
objectId = castAsInteger(data.object);
objectType = castAsInteger(data.type);
liked = castAsInteger(data.like);

if(! (commentId && objectId && objectType )) { return false; }

// make an ajax request to like/dislike a comment
$.post(`/ajax.php?action=likeComment&commentId=${commentId}&objectId=${objectId}&objectType=${objectType}&liked=${liked}`, {})
.done(function(payload){
if(payload.error === true) {
location.reload();
return false;
}

// remove all active classes before proceed
$("#commentRow" + commentId + " button").removeClass("active");

// check which button should be activated
switch(true) {
case payload.data.hasLiked == 1:
$("#commentRow" + commentId + " .like-form button").addClass("active");
break;
case payload.data.hasDisliked == 1:
$("#commentRow" + commentId + " .dislike-form button").addClass("active");
break;
default:
break;
}

// update scores
$("#commentRow" + commentId + " .like-form .likeCounter").html(castAsInteger(payload.data.totalLikes));
$("#commentRow" + commentId + " .dislike-form .likeCounter").html(castAsInteger(payload.data.totalDislikes));

}).fail(function(){ return false; })
;
}

var replyhandler = function(e) {

e.preventDefault();
data = $(this).data();
// form elements
const subReplyClass = data.reply ? "post-form-subreply" : "";
const dataReplyBox = data.reply ? data.reply : data.parent;
const authorHiddenInput = data.author ? "<input type='hidden' name='authorId' value='" + castAsInteger(data.author) + "'>" : "";
const placeholder = escapeHtml(data.profile);

// build reply box html structure
replyHtml = `
<form method='post' id='postComment' class='post-comment-form post-form-reply ${subReplyClass}' action='#comments'>
<input type='hidden' name='action' value='addComment'>
<input type='hidden' name='commentType' value='${data.type}'>
<input type='hidden' name='parentId' value='${data.parent}'>
<input type='hidden' name='objectId' value='${data.object}'>
${authorHiddenInput}
<textarea class='form-control' placeholder="Reply to ${placeholder}" name='comment' maxlength='2000'></textarea>
<button type='submit' class='btn btn-success post-comment-btn'>Post</button>
<button class='btn btn-danger cancel-reply' data-replybox='${dataReplyBox}'>Cancel</button>
</form>
`;

// set reply box html
$("#replyBox" + (data.reply ? data.reply : data.parent )).html(replyHtml);

// bind cancel buttons actions
bindCancelButtons();
};

+ 6
- 0
html/js/jquery-1.10.2.min.js
File diff suppressed because it is too large
View File


+ 4
- 0
html/js/jquery.fancybox.pack.js
File diff suppressed because it is too large
View File


+ 5
- 0
html/js/site.js View File

@@ -0,0 +1,5 @@
$(document).ready(function(){$('[data-toggle="tooltip"]').tooltip({container:'body'});$('.navbar-toggle').click(function(){$(this).toggleClass('activated');});$(".toggle-search").click(function(){$('.overlay-search').toggleClass('display-overlay');});$('body').on("click",".dropdown-menu",function(e){$(this).parent().is(".open")&&e.stopPropagation();});$("form").each(function(){})
$('input[type="file"]').change(function(e){var maxsize=parseInt($(this).attr("data-maxfilesize"));if(!maxsize){return;}
if(this.files[0].size>maxsize){alert('Sorry, that file size exceeds the maximum allowed size of '+parseInt(maxsize/1024/1024)+'Mb');$(this).val('');}});});function scrollTop(){return document.body.scrollTop||document.documentElement.scrollTop;}
function debounce(func,wait,immediateFunc){var timeout;return function(){var context=this,args=arguments;var later=function(){timeout=null;func.apply(context,args);};if(immediateFunc){immediateFunc.apply(context,args);}
clearTimeout(timeout);timeout=setTimeout(later,wait);};};

+ 5
- 3
main.py View File

@@ -31,7 +31,9 @@ def main(args: dict) -> None:
infovaya_creds_request = infovaya_session.post(f"{INFOVAYA_ROOT}login", data=info)
infovaya_creds_request.raise_for_status()

sessions_request = infovaya_session.get("{}event?id=88&actionMenu=sessions".format(INFOVAYA_ROOT))
root_event = 88 if not args.event else args.event

sessions_request = infovaya_session.get(f"{INFOVAYA_ROOT}event?id={root_event}&actionMenu=sessions")
sessions_request.raise_for_status()
sessions_page_soup = BeautifulSoup(sessions_request.text, "html.parser")
if args.save_pages:
@@ -83,8 +85,8 @@ def main(args: dict) -> None:

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-s", "--save-pages", action="store_true", help="Save HTML of ")
# parser.add_argument("-i", "--images", action="store_true", help="Set this flag to download images as well as HTML.\nNOTE: This may be VERY bandwidth and disk intensive!")
parser.add_argument("-s", "--save-pages", action="store_true", help="Save HTML of the scanned pages")
parser.add_argument("-e", "--event", action="store_true", help="Choose which event ID to scan")
args = parser.parse_args()
print(args)
main(args)

Loading…
Cancel
Save