Skip to content

Instantly share code, notes, and snippets.

@noimin0610
Last active December 2, 2018 07:10
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 noimin0610/3784eefdc9de0bf35cd29ada6c879ad0 to your computer and use it in GitHub Desktop.
Save noimin0610/3784eefdc9de0bf35cd29ada6c879ad0 to your computer and use it in GitHub Desktop.
AtCoder Performances ソースコード (一部)
from django.shortcuts import render
from django.views.generic import FormView
from .utils.error_reporter import report_error_if_violates as report_vio
from .utils.atcoder_history import AtCoderUserHistory, AtCoderUserHistoryStatistics
from .utils.atcoder_figure import AtCoderFigure
from .utils.base64_graph import base64_png
from .forms import UserNamesForm
from atcoderapps.settings import SOCIAL_AUTH_TWITTER_KEY, SOCIAL_AUTH_TWITTER_SECRET
from django.contrib.auth.decorators import login_required
from social_django.models import UserSocialAuth
import json
import base64
from requests_oauthlib import OAuth1Session
import os, os.path
MAX_RIVAL_NUM = 4
MEDIA_URL = "https://upload.twitter.com/1.1/media/upload.json"
TWEET_URL = "https://api.twitter.com/1.1/statuses/update.json"
class IndexView(FormView):
template_name = "atcoderperformances/index.html"
form_class = UserNamesForm
def get_form(self):
form = super(IndexView, self).get_form()
form.set_attr("username", {
"tabindex": 1,
"class": "form-control",
"placeholder": "ex. Noimin"
})
form.set_attr("rivalname", {
"tabindex": 2,
"class": "form-control",
"placeholder": "ex. Noimin,fuurin"
})
return form
class ShowGraphView(FormView):
template_name = "atcoderperformances/show_graph.html"
form_class = UserNamesForm
def parse_rivals(self, cs_rivalnames):
rivals = list(set(cs_rivalnames.replace(" ", "").split(",")))
if "" in rivals: rivals.remove("")
return rivals
def check_rivals_num(self, rivals):
violates = len(rivals) > MAX_RIVAL_NUM
msg = "Number of rivals is up to &nbsp;<strong>{}</strong>.".format(MAX_RIVAL_NUM)
report_vio(self.request, violates, msg)
return not violates
def check_all_hist_existenses(self, hists):
not_found_usernames = [hist.name for hist in hists if not hist.exists]
violates = len(not_found_usernames) > 0
msg = "Histories of &nbsp;<strong>{}</strong>&nbsp;could not be found.".format(", ".join(not_found_usernames))
report_vio(self.request, violates, msg)
def check_time_cross_over(self, since, until):
violates = since > until
msg = "Since cannot be after Until."
report_vio(self.request, violates, msg)
def get_form(self):
form = super(ShowGraphView, self).get_form()
form.set_attr("username", {
"value": self.username,
"tabindex": 1,
"class": "form-control",
"placeholder": "ex. Noimin"
})
form.set_attr("rivalname", {
"value": self.rivalname,
"tabindex": 2,
"class": "form-control",
"placeholder": "ex. Noimin,fuurin"
})
return form
def get_context_data(self, **kwargs):
if 'params' in self.request.GET:
params = self.request.GET.get('params').split('_')
username = self.username = params[0]
rivalname = self.rivalname = params[1]
since = params[2]
until = params[3]
else:
username = self.username = self.request.GET.get("username")
rivalname = self.rivalname = self.request.GET.get("rivalname")
since = self.request.GET.get('since')
until = self.request.GET.get('until')
if username == None: username = self.username = ""
if rivalname == None: rivalname = self.rivalname = ""
context = super().get_context_data(**kwargs)
context['username'], context['rivalname'] = username, rivalname
rivalnames = self.parse_rivals(rivalname)
if not self.check_rivals_num(rivalnames): rivalnames = []
hists = [AtCoderUserHistory(name) for name in [username] + rivalnames if name != ""]
self.check_all_hist_existenses(hists)
statistics = AtCoderUserHistoryStatistics(hists)
context['atcoder_times'] = [str(time.date()) for time in statistics.times()]
if context['atcoder_times']:
if since:
context['since'] = since
hists = [hist.since(since) for hist in hists]
else:
context['since'] = context['atcoder_times'][0]
if until:
context['until'] = until
hists = [hist.until(until) for hist in hists]
else:
context['until'] = context['atcoder_times'][-1]
if since and until: self.check_time_cross_over(since, until)
statistics = AtCoderUserHistoryStatistics(hists)
context['figure'] = base64_png(AtCoderFigure(hists).make_performances_figure())
context['atcoder_statistics'] = statistics().round(2)
try:
user = UserSocialAuth.objects.get(user_id=self.request.user.id)
except:
context['user'] = None
else:
context['user'] = user
if 'tweet' in self.request.GET:
tweet_url = self.tweet(context)
violates = (tweet_url == None)
if violates:
msg = "Tweet failed."
report_vio(self.request, violates, msg)
else:
context['tweet_url'] = tweet_url
return context
def tweet(self, context):
# セッション開始
user = context['user']
session = OAuth1Session(
SOCIAL_AUTH_TWITTER_KEY,
SOCIAL_AUTH_TWITTER_SECRET,
user.access_token['oauth_token'],
user.access_token['oauth_token_secret']
)
# ローカルに画像を保存
figure = context['figure']
file_path = "{}/{}_{}_{}_{}.png".format(
os.path.join(
os.path.dirname(__file__),
'tmp'
),
context['username'],
context['rivalname'],
context['since'],
context['until']
)
with open(file_path, 'wb') as f:
f.write(base64.b64decode(figure))
with open(file_path, 'rb') as f:
# 画像アップロード
files = {"media" : f}
media_request = session.post(MEDIA_URL, files=files)
if media_request.status_code != 200:
f.close()
os.remove(file_path)
return None
# 画像付きツイート
media_id = json.loads(media_request.text)['media_id']
status = "Performances of {}{}{} ({}〜{}) https://atcoderapps.herokuapp.com/atcoderperformances/ #AtCoder_Performances".format(
context['username'],
", " if len(context['rivalname']) else " ",
", ".join(context['rivalname'].split(',')),
context['since'],
context['until']
)
params = {'status': status, "media_ids": [media_id]}
tweet_request = session.post(TWEET_URL, params=params)
if tweet_request.status_code != 200:
f.close()
os.remove(file_path)
return None
os.remove(file_path)
tweet_url = json.loads(tweet_request.text)["entities"]["media"][0]["expanded_url"]
return tweet_url
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment