summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--py-fake-service/app/adapter/__init__.py2
-rw-r--r--py-fake-service/app/adapter/contacts.py19
-rw-r--r--py-fake-service/app/adapter/mail.py12
-rw-r--r--py-fake-service/app/adapter/mail_service.py33
-rw-r--r--py-fake-service/app/adapter/mailset.py8
-rw-r--r--py-fake-service/app/adapter/tag.py17
-rw-r--r--py-fake-service/app/adapter/tagsset.py16
-rw-r--r--py-fake-service/app/pixelated_user_agent.py19
-rw-r--r--py-fake-service/app/search/__init__.py1
-rw-r--r--py-fake-service/app/search/search_query.py65
11 files changed, 173 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 207be4cc..6a9b42dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,4 @@ env/
fake-service/data/mail-sets/
.vagrant/
__pycache__/
+.virtualenv
diff --git a/py-fake-service/app/adapter/__init__.py b/py-fake-service/app/adapter/__init__.py
index 8b137891..47addd32 100644
--- a/py-fake-service/app/adapter/__init__.py
+++ b/py-fake-service/app/adapter/__init__.py
@@ -1 +1 @@
-
+from mail_service import MailService
diff --git a/py-fake-service/app/adapter/contacts.py b/py-fake-service/app/adapter/contacts.py
new file mode 100644
index 00000000..45aa2177
--- /dev/null
+++ b/py-fake-service/app/adapter/contacts.py
@@ -0,0 +1,19 @@
+import re
+
+class Contacts:
+ def __init__(self):
+ self.contacts = []
+
+ def add(self, mbox_mail):
+ contact = mbox_mail.get_from()
+ self.contacts.append(Contact(contact))
+
+ def search(self, query):
+ contacts_query = re.compile(query)
+ return [contact.__dict__ for contact in self.contacts if contacts_query.match(contact.addresses[0])]
+
+class Contact:
+ def __init__(self, contact):
+ self.addresses = [contact]
+ self.name = ''
+
diff --git a/py-fake-service/app/adapter/mail.py b/py-fake-service/app/adapter/mail.py
index 1140f062..859eb50c 100644
--- a/py-fake-service/app/adapter/mail.py
+++ b/py-fake-service/app/adapter/mail.py
@@ -1,4 +1,5 @@
from datetime import datetime
+import random
class Mail:
@@ -13,14 +14,15 @@ class Mail:
def _get_headers(self, mbox_mail):
headers = {}
headers['from'] = mbox_mail.get_from()
- headers['to'] = [mbox_mail.items()['To']]
- headers['subject'] = mbox_mail.items()['Subject']
+ headers['to'] = [mbox_mail.get('To')]
+ headers['subject'] = mbox_mail.get('Subject')
headers['date'] = datetime.fromtimestamp(random.randrange(1222222222, 1444444444)).isoformat()
return headers
def _get_tags(self, mbox_mail):
- return mbox_mail.items()['X-TW-Pixelated-Tags'].split(', ')
-
-
+ return mbox_mail.get('X-TW-Pixelated-Tags').split(', ')
+ @property
+ def subject(self):
+ return self.headers['subject']
diff --git a/py-fake-service/app/adapter/mail_service.py b/py-fake-service/app/adapter/mail_service.py
index b657e59a..649ea96e 100644
--- a/py-fake-service/app/adapter/mail_service.py
+++ b/py-fake-service/app/adapter/mail_service.py
@@ -1,19 +1,38 @@
import os
import mailbox
+from tagsset import TagsSet
+from mailset import MailSet
+from contacts import Contacts
class MailService:
- MAILSET_PATH = os.join(os.environ('HOME'), 'mailset', 'mediumtagged'))
+ MAILSET_PATH = os.path.join(os.environ['HOME'], 'mailsets', 'mediumtagged')
def __init__(self):
- self.mails = MailSet()
+ self.mailset = MailSet()
+ self.tagsset = TagsSet()
+ self.contacts = Contacts()
def load_mailset(self):
- mbox_filenames = [filename for filename in os.listdir(MAILSET_PATH) if mbox.startswith('mbox')]
- boxes = (mailbox.mbox(os.path.join(MAILSET_PATH, mbox)) for mbox in mbox_filenames)
+ mbox_filenames = [filename for filename in os.listdir(self.MAILSET_PATH) if filename.startswith('mbox')]
+ boxes = (mailbox.mbox(os.path.join(self.MAILSET_PATH, mbox)) for mbox in mbox_filenames)
for box in boxes:
- message = box.popitem()
- self.mails.add(message[1])
+ message = box.popitem()[1]
+ if message.is_multipart():
+ continue
+ self.mailset.add(message)
+ self.tagsset.add(message)
+ self.contacts.add(message)
+
+ def mails(self, query, page, window_size):
+ mails = self.mailset.values()
+ mails = [mail for mail in mails if query.test(mail)]
+ return mails
+
+ def mail(self, mail_id):
+ return self.mailset.get(mail_id)
+
+ def search_contacts(self, query):
+ return self.contacts.search(query)
-
diff --git a/py-fake-service/app/adapter/mailset.py b/py-fake-service/app/adapter/mailset.py
index d81600e0..2b1627ae 100644
--- a/py-fake-service/app/adapter/mailset.py
+++ b/py-fake-service/app/adapter/mailset.py
@@ -8,7 +8,13 @@ class MailSet:
self.mails = {}
def add(self, mbox_mail):
- self.mails[self.ident] = Mail(mbox_mail)
+ self.mails[self.ident] = Mail(mbox_mail, self.ident)
self.ident += 1
+ def values(self):
+ return self.mails.values()
+
+ def get(self, mail_id):
+ return self.mails.get(int(mail_id))
+
diff --git a/py-fake-service/app/adapter/tag.py b/py-fake-service/app/adapter/tag.py
new file mode 100644
index 00000000..bc98669d
--- /dev/null
+++ b/py-fake-service/app/adapter/tag.py
@@ -0,0 +1,17 @@
+class Tag:
+ DEFAULT_TAGS = ["inbox", "sent", "trash", "drafts"]
+
+ def __init__(self, name, ident):
+ self.counts = {
+ 'total': 1,
+ 'read': 0,
+ 'starred': 0,
+ 'reply': 0
+ }
+
+ self.ident = ident
+ self.name = name
+ self.default = name in self.DEFAULT_TAGS
+
+ def increment_count(self):
+ self.counts['total'] += 1
diff --git a/py-fake-service/app/adapter/tagsset.py b/py-fake-service/app/adapter/tagsset.py
new file mode 100644
index 00000000..23941735
--- /dev/null
+++ b/py-fake-service/app/adapter/tagsset.py
@@ -0,0 +1,16 @@
+from tag import Tag
+
+class TagsSet:
+ def __init__(self):
+ self.tags = {}
+ self.ident = 0
+
+ def add(self, mbox_mail):
+ tags = mbox_mail.get('X-TW-Pixelated-Tags').split(', ')
+ for tag in tags:
+ tag = self.tags.setdefault(tag, Tag(tag, self.ident))
+ tag.increment_count()
+ self.ident += 1
+
+ def all_tags(self):
+ return self.tags.values()
diff --git a/py-fake-service/app/pixelated_user_agent.py b/py-fake-service/app/pixelated_user_agent.py
index 62ccd206..20ccadcc 100644
--- a/py-fake-service/app/pixelated_user_agent.py
+++ b/py-fake-service/app/pixelated_user_agent.py
@@ -3,6 +3,8 @@ from flask import Flask, request, Response, redirect
import json
import datetime
import requests
+from adapter import MailService
+from search import SearchQuery
app = Flask(__name__, static_url_path='', static_folder='../../web-ui/app')
client = None
@@ -32,7 +34,12 @@ def update_draft():
@app.route('/mails')
def mails():
- mails = []
+ query = SearchQuery.compile(request.args.get('q', ''))
+ page = request.args.get('p', '')
+ window_size = request.args.get('w', '')
+ fetched_mails = mail_service.mails(query, page, window_size)
+
+ mails = [mail.__dict__ for mail in fetched_mails]
response = {
"stats": {
"total": len(mails),
@@ -53,13 +60,13 @@ def delete_mails(mail_id):
@app.route('/tags')
def tags():
- tags = []
- return respond_json(tags)
+ tags = mail_service.tagsset.all_tags()
+ return respond_json([tag.__dict__ for tag in tags])
@app.route('/mail/<mail_id>')
def mail(mail_id):
- return respond_json({})
+ return respond_json(mail_service.mail(mail_id).__dict__)
@app.route('/mail/<mail_id>/tags')
@@ -71,10 +78,10 @@ def mail_tags(mail_id):
def mark_mail_as_read(mail_id):
return ""
-
@app.route('/contacts')
def contacts():
- return respond_json({'contacts': []})
+ contacts_query = request.args.get('q')
+ return respond_json({'contacts': mail_service.search_contacts(contacts_query)})
@app.route('/draft_reply_for/<mail_id>')
diff --git a/py-fake-service/app/search/__init__.py b/py-fake-service/app/search/__init__.py
new file mode 100644
index 00000000..da90bc7f
--- /dev/null
+++ b/py-fake-service/app/search/__init__.py
@@ -0,0 +1 @@
+from search_query import SearchQuery
diff --git a/py-fake-service/app/search/search_query.py b/py-fake-service/app/search/search_query.py
new file mode 100644
index 00000000..cb8d5f57
--- /dev/null
+++ b/py-fake-service/app/search/search_query.py
@@ -0,0 +1,65 @@
+from scanner import StringScanner, StringRegexp
+import re
+
+
+def _next_token():
+ return StringRegexp('[^\s]+')
+
+
+def _separators():
+ return StringRegexp('[\s&]+')
+
+
+def _compile_tag(compiled, token):
+ tag = token.split(":").pop()
+ if token[0] == "-":
+ compiled["not_tags"].append(tag)
+ else:
+ compiled["tags"].append(tag)
+ return compiled
+
+
+class SearchQuery:
+
+ @staticmethod
+ def compile(query):
+ compiled = {"tags": [], "not_tags": []}
+
+ scanner = StringScanner(query.encode('utf8').replace("\"", ""))
+ first_token = True
+ while not scanner.is_eos:
+ token = scanner.scan(_next_token())
+
+ if not token:
+ scanner.skip(_separators())
+ continue
+
+ if ":" in token:
+ compiled = _compile_tag(compiled, token)
+ elif first_token:
+ compiled["general"] = token
+
+ if not first_token:
+ first_token = True
+
+ return SearchQuery(compiled)
+
+ def __init__(self, compiled):
+ self.compiled = compiled
+
+ def test(self, mail):
+ if set(self.compiled.get('tags')).intersection(mail.tags) or 'all' in self.compiled.get('tags'):
+ return True
+
+ if self.compiled.get('general'):
+ search_terms = re.compile(self.compiled['general'])
+ if search_terms.match(mail.body) or search_terms.match(mail.subject):
+ return True
+
+ if not self.compiled.get('tags') and not self.compiled.get('not_tags'):
+ return True
+
+ return False
+
+
+