Last active
December 8, 2016 20:58
-
-
Save anta0/6533ffd4ba792bd67b5d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name SmartSubmit for AtCoder | |
// @version 0.200001 | |
// @auther anta | |
// @description 問題閲覧画面で Ctrl+V をするだけで提出します。yukicoder <http://yukicoder.me/> の機能・コードを元にしています。 | |
// @match http://*.contest.atcoder.jp/* | |
// @match https://*.contest.atcoder.jp/* | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @grant GM_listValues | |
// @grant GM_xmlhttpRequest | |
// @run-at document-end | |
// ==/UserScript== | |
//License: MPL <https://www.mozilla.org/MPL/2.0/> | |
//Changelog: | |
//0.1: init | |
//0.2: add: isValidSource | |
//0.2: fix | |
//指定したい言語にマッチする正規表現 (コンテストによって使えるバージョンが違うことがあるので適切に) | |
var languageNameMatch = /C\+\+11 \(GCC [\d\.]+\)/.source; | |
//変な文字列とかを間違って提出してしまわないように | |
var sourceRegExp = /^#include/; | |
function log() { | |
console.log.apply(console, arguments); | |
} | |
function getTaskID() { | |
var href = $(".btn-large").attr("href"); | |
if(!href) return null; | |
var match = href.match(/^\/submit\?task_id=(.*)$/); | |
if(!match) return null; | |
return match[1]; | |
} | |
function getVar(name) { | |
return GM_getValue(name); | |
} | |
function setVar(name, val) { | |
GM_setValue(name, val); | |
} | |
function getSessionID(callback) { | |
var sessionCookie = $.cookie('_session'); | |
if(getVar('sessionCookie') != sessionCookie || !getVar('cachedSessionID')) { | |
var err = function() { | |
log.apply(this, arguments); | |
}; | |
if(sessionCookie) GM_xmlhttpRequest({ | |
method: 'GET', | |
url: 'https://' + location.host + '/submit', | |
onload: function(r) { | |
var data = r.responseText; | |
var match = data.match(/name="__session" value="([0-9a-f]+)"/); | |
if(!match) { | |
// err('err', data); | |
return; | |
} | |
var sessionID = match[1]; | |
setVar('sessionCookie', sessionCookie); | |
setVar('cachedSessionID', sessionID); | |
log('sessionID: ' + sessionID + ' for cookie ' + sessionCookie); | |
callback(sessionID); | |
}, | |
onerror: err | |
}); | |
}else { | |
callback(getVar('cachedSessionID')); | |
} | |
} | |
function getLanguageID(callback) { | |
var host = location.host, cacheName = 'cachedLanguageID[' + host + ']'; | |
if(!getVar(cacheName)) { | |
var err = function() { | |
log.apply(this, arguments); | |
}; | |
GM_xmlhttpRequest({ | |
method: 'GET', | |
url: 'https://' + location.host + '/submit', | |
onload: function(r) { | |
var data = r.responseText; | |
var match = data.match(new RegExp('<option value="([^"]+)">(' + languageNameMatch + ')</option>')); | |
if(!match) { | |
err('language not found'); | |
return; | |
} | |
var languageID = match[1]; | |
setVar(cacheName, languageID); | |
log('languageID: ' + languageID + ' ' + match[2] + ''); | |
callback(languageID); | |
}, | |
onerror: err | |
}); | |
}else { | |
callback(getVar(cacheName)); | |
} | |
} | |
function isValidSource(source) { | |
if(!source) return false | |
if(!source.match(sourceRegExp)) return false; | |
return true; | |
} | |
//log('start'); | |
getSessionID(function(sessionID) { | |
var taskID = getTaskID(); | |
if(!taskID) return; | |
getLanguageID(function(languageID) { | |
log('taskID = ' + taskID + ', sessionID = ' + sessionID); | |
$('body').append($('<form action="https://' + location.host + '/submit?task_id=' + taskID + '" method="POST">'+ | |
'<input type="hidden" name="__session" value="' + sessionID + '">'+ | |
'<input type="hidden" name="task_id" value="' + taskID + '">'+ | |
'<input type="hidden" name="language_id_' + taskID + '" value="' + languageID + '">'+ | |
'<textarea name="source_code" id="smartsubmit-source" style="display: none; position: fixed"></textarea>'+ | |
'<input type="submit" id="smartsubmit-submit" style="display: none">'+ | |
'</form>')); | |
$(document).keydown(function(e){ | |
var keyEvent = e || window.event; | |
//macのコマンドキーまたはコントロールキー | |
if(keyEvent.metaKey || keyEvent.ctrlKey){ | |
//選択範囲がある時は動作しない。 | |
var selObj = window.getSelection(); | |
if (selObj.toString().length == 0 || keyEvent.keyCode == 86){ | |
$("#smartsubmit-source").val("").show().focus(); | |
} | |
} | |
}); | |
$("#smartsubmit-source").keyup(function(e){ | |
var keyEvent = e || window.event; | |
if(keyEvent.metaKey || keyEvent.ctrlKey){ | |
}else{ | |
$("#smartsubmit-source").hide(); | |
} | |
}); | |
$('#smartsubmit-source').bind('paste',function(ev){ | |
var source = ev.originalEvent.clipboardData.getData('text/plain'); | |
if(isValidSource(source)) { | |
setTimeout(function() { | |
$("#smartsubmit-source").val(source); | |
$("#smartsubmit-source").hide(); | |
$("#smartsubmit-submit").click(); | |
}, 10); | |
}else { | |
log("invalid source: " + source); | |
$("#smartsubmit-source").val(''); | |
} | |
}); | |
})}); | |
/* | |
GM_listValues().forEach(function(val) { | |
console.log(val, GM_getValue(val)); | |
}); | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment