diff --git a/README b/README deleted file mode 100644 index 4033722..0000000 --- a/README +++ /dev/null @@ -1,18 +0,0 @@ -Folks who worked at Google may miss snippets at their current -employers. Help is at hand. - -Every week, the system emails out a reminder email. Users can reply to -it with what they did that week. Users can follow other users via the -web, as well as following tags, and assigning tags to themselves. All -content matching the tags they follow will be mailed to them in a -digest every Monday afternoon. In addition, archives for each user and -the most recent data for each tag are visible on the web. - -It was hard to make this totally portable. You'll probably want to -fork and change the application name and hardcoded email addresses, -creating your own application on app engine with authentication -restricted to your custom domain. I would love patches to core -functionality, though. - -Little attention has been paid to making this particularly scalable, -but it should work for any small or medium company. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b49cf8f --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# 스니펫 +Snippets는 구글이 사내에서 운영하는 업무 공유용 이메일 시스템입니다. + +### 스니펫 동작 방식 + +매주, 스니펫 시스템으로부터 리마인더 이메일이 발송됩니다. +사용자들은 지난 주에 무엇을 했는지 여기에 답변으로 보낼 수 있습니다. +웹을 통해 다른 사용자들을 follow 할 수 있습니다. +태그 기능도 있어서 자기 자신을 태그에 할당하고, 이렇게 생긴 태그 역시 follow 할 수 있습니다. +그러고나면 매주 월요일에 follow 한 태그나 사용자에 대한 다이제스트 메일을 받게 됩니다. +추가로 각 사용자들의 아카이브도 웹에서 볼 수 있습니다. + +**fork 후 수정 내용 - 특이사항 없음** + +* 타임존을 서울/아시아로 변경 +* 수정할 부분 FIX ME로 표시 +* 가입 계정 소문자 변환 +* 서명, 답변 패턴 추가 + +### 사용하기 +1. git clone git@github.com:curioe/snippets.git +2. [구글앱엔진](https://appengine.google.com) 에서 새 앱을 생성합니다. +3. 소스를 생성한 이름에 맞게 수정합니다. ('FIX ME'로 검색) +4. 구글앱엔진 런처를 실행하여, 또는 커맨드로 배포하면 완료됩니다. +5. 웹 - {앱명}.appspot.com 과, 메일 - snippets@{앱명}.appsotmail.com 을 통해 스니펫을 시작하면 됩니다. :) + +### 나에게 맞게 수정 +* trim될 서명, 답변 패턴을 정규식으로 추가 -> receive_email.py +* 리마인더/다이제스트 메일 발송 시각 변경 -> cron.yaml + + + + +----- +# Original README +Folks who worked at Google may miss snippets at their current +employers. Help is at hand. + +Every week, the system emails out a reminder email. Users can reply to +it with what they did that week. Users can follow other users via the +web, as well as following tags, and assigning tags to themselves. All +content matching the tags they follow will be mailed to them in a +digest every Monday afternoon. In addition, archives for each user and +the most recent data for each tag are visible on the web. + +It was hard to make this totally portable. You'll probably want to +fork and change the application name and hardcoded email addresses, +creating your own application on app engine with authentication +restricted to your custom domain. I would love patches to core +functionality, though. + +Little attention has been paid to making this particularly scalable, +but it should work for any small or medium company. \ No newline at end of file diff --git a/app.yaml b/app.yaml index 558f111..458051d 100755 --- a/app.yaml +++ b/app.yaml @@ -1,10 +1,14 @@ -application: fssnippets +application: minisnippets # FIX ME version: 1 runtime: python api_version: 1 handlers: -- url: /_ah/mail/snippets@.*fssnippets\.appspotmail\.com +- url: /favicon.ico + static_files: templates/favicon.ico + upload: templates/favicon.ico + +- url: /_ah/mail/snippets@.*minisnippets\.appspotmail\.com # FIX ME script: receive_email.py login: admin diff --git a/cron.yaml b/cron.yaml index d45a135..66d41bc 100644 --- a/cron.yaml +++ b/cron.yaml @@ -1,9 +1,9 @@ cron: - description: weekly reminder url: /reminderemail - schedule: every sunday 19:00 - timezone: America/New_York + schedule: every friday 17:00 # FIX ME + timezone: Asia/Seoul - description: weekly digest url: /digestemail - schedule: every monday 19:00 - timezone: America/New_York + schedule: every monday 9:00 # FIX ME + timezone: Asia/Seoul diff --git a/dateutil.py b/dateutil.py index 2f98890..cb393f3 100644 --- a/dateutil.py +++ b/dateutil.py @@ -1,18 +1,19 @@ import datetime -class Eastern_tzinfo(datetime.tzinfo): - """Implementation of the Eastern timezone. +class Seoul_tzinfo(datetime.tzinfo): + """Implementation of the Seoul timezone. Adapted from http://code.google.com/appengine/docs/python/datastore/typesandpropertyclasses.html """ def utcoffset(self, dt): - return datetime.timedelta(hours=-5) + self.dst(dt) + return datetime.timedelta(hours=+9) + self.dst(dt) def _FirstSunday(self, dt): """First Sunday on or after dt.""" return dt + datetime.timedelta(days=(6-dt.weekday())) def dst(self, dt): + """ 한국은 섬머타임 없으므로 계산 생략 (dst=daylight saving time) # 2 am on the second Sunday in March dst_start = self._FirstSunday(datetime.datetime(dt.year, 3, 8, 2)) # 1 am on the first Sunday in November @@ -22,17 +23,21 @@ def dst(self, dt): return datetime.timedelta(hours=1) else: return datetime.timedelta(hours=0) - + """ + return datetime.timedelta(hours=0) + def tzname(self, dt): + """ if self.dst(dt) == datetime.timedelta(hours=0): - return "EST" + return "KST" else: - return "EDT" - + return "KDT" + """ + return "KST" def date_for_new_snippet(): """Return next Monday, unless it is Monday (0) or Tuesday (1)""" - today = datetime.datetime.now(Eastern_tzinfo()).date() + today = datetime.datetime.now(Seoul_tzinfo()).date() if (today.weekday() < 2): aligned = today - datetime.timedelta(days=today.weekday()) else: @@ -42,5 +47,5 @@ def date_for_new_snippet(): def date_for_retrieval(): """Always return the most recent Monday.""" - today = datetime.datetime.now(Eastern_tzinfo()).date() + today = datetime.datetime.now(Seoul_tzinfo()).date() return today - datetime.timedelta(days=today.weekday()) diff --git a/emails.py b/emails.py index 00a554f..78eb6ec 100644 --- a/emails.py +++ b/emails.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import logging from google.appengine.api import mail @@ -9,9 +10,14 @@ from model import * REMINDER = """ -Hey nerd, +한 주간 수고하셨습니다. +회신으로 업무내역을 입력해주세요. :) -The kids want to know what you're up to. Don't leave 'em hanging. +지난주 한 일 +- + +이번주 할 일 +- """ class ReminderEmail(webapp.RequestHandler): @@ -24,9 +30,9 @@ def get(self): class OneReminderEmail(webapp.RequestHandler): def post(self): - mail.send_mail(sender="snippets ", + mail.send_mail(sender="snippets ", # FIX ME to=self.request.get('email'), - subject="Snippet time!", + subject="Snippet 타임!", body=REMINDER) def get(self): @@ -41,9 +47,9 @@ def get(self): class OneDigestEmail(webapp.RequestHandler): def __send_mail(self, recipient, body): - mail.send_mail(sender="snippets ", + mail.send_mail(sender="snippets ", # FIX ME to=recipient, - subject="Snippet delivery!", + subject="Snippet Digest 메일이 도착하였습니다!", body=body) def __snippet_to_text(self, snippet): @@ -62,6 +68,6 @@ def post(self): logging.info(all_snippets) body = '\n\n\n'.join([self.__snippet_to_text(s) for s in all_snippets if s.user.email in following]) if body: - self.__send_mail(user.email, 'https://fssnippets.appspot.com\n\n' + body) + self.__send_mail(user.email, 'https://minisnippets.appspot.com\n\n' + body) # FIX ME else: logging.info(user.email + ' not following anybody.') diff --git a/main.py b/main.py index 66cfe79..600266d 100755 --- a/main.py +++ b/main.py @@ -42,7 +42,8 @@ def wrapper(self, *args, **kwargs): class BaseHandler(webapp.RequestHandler): def get_user(self): '''Returns the user object on authenticated requests''' - user = users.get_current_user() + curuser = users.get_current_user() + user = users.User(curuser.email().lower()) assert user userObj = User.all().filter("email =", user.email()).fetch(1) diff --git a/receive_email.py b/receive_email.py index 9b2db9e..1e58b00 100644 --- a/receive_email.py +++ b/receive_email.py @@ -21,11 +21,11 @@ def receive(self, message): body.encoding = '7bit' content = body.decode() - sig_pattern = re.compile(r'^\-\-\s*$', re.MULTILINE) + sig_pattern = re.compile(r'^(\-\-|\=\=)\s*$', re.MULTILINE) split_email = re.split(sig_pattern, content) content = split_email[0] - reply_pattern = re.compile(r'^On.*at.*snippets', re.MULTILINE) + reply_pattern = re.compile(r'^(On.*at|2\d{3}).*snippets', re.MULTILINE) split_email = re.split(reply_pattern, content) content = split_email[0] diff --git a/templates/base.html b/templates/base.html index f4edfb2..cf83dbc 100644 --- a/templates/base.html +++ b/templates/base.html @@ -7,11 +7,11 @@ a.light { color: #AAA; text-decoration: none } a.light:hover { text-decoration: underline } - {% block title %}snippets{% endblock %} + {% block title %}mini snippets{% endblock %} -

snippets

+

미니 스니펫

{% block body %} {% endblock %} diff --git a/templates/favicon.ico b/templates/favicon.ico new file mode 100644 index 0000000..9afdeea Binary files /dev/null and b/templates/favicon.ico differ diff --git a/templates/index.html b/templates/index.html index 3a174b5..6050598 100644 --- a/templates/index.html +++ b/templates/index.html @@ -17,8 +17,27 @@

{{ current_user.pretty_name }}<
- - send your snippets to snippets@fssnippets.appspotmail.com by monday afternoon! + +

스니펫 사용법

+ 스니펫을 일요일까지 보내주세요: snippets@minisnippets.appspotmail.com +

+ 리마인더 메일은 금요일 오후 5시, 다이제스트 메일은 월요일 오전 9시에 발송됩니다. +

+ 스니펫 작성 날짜에 따른 입력 기준 +
    +
  • 월요일에 작성 => 해당주 입력됨
  • +
  • 화~일요일에 작성 => 다음주 입력됨
  • +
+ 스니펫 메일을 다시 보내면 수정할 수 있습니다. +

+ 서명 문자(== 또는 --) 이후는 trim 되어 입력됩니다. +

+

스니펫 기본 설정

+
    +
  1. 자신의 태그란에 팀명을 넣어주세요.
  2. +
  3. 이메일이나 태그를 follow 해주세요. 다이제스트 메일로 발송됩니다.
  4. +
+