diff --git a/README.md b/README.md index 8d010d6..49c64d0 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,20 @@ Provide a [twister](twister.net.co) web client that: In short: it's a "twister-client constructor kit". Even if what you do doesn't get merged upstream, who says we should all run the same client? Diversity is fun. ### Roadmap -The following functionality is missing before Swizzler becomes a full read-only version +Missing features before Swizzler has full read-only functionality -* Direct messages - currently, there are links to that (look like an envelope) but they're 404 ;) * Search box - for hashtags and users by prefix -* Basic auth - we don't want trojans to read our direct messages, so I guess this is top priority ;) +* Direct messages +* Basic auth -I believe this should take a few days. +We're almost there \o/ #### Future -* *To be defined* +* [db instead of cache](https://github.com/swizzler/swizzler/wiki/from-cache-to-db) +* Full [or almost full] functionality of the standard client +* [additional features](https://github.com/swizzler/swizzler/wiki/Ideas-for-features) +* *Insert here stuff I've overlooked* * Then we take Berlin ---------------- diff --git a/swizzler.py b/swizzler.py index 6741ba9..6403d61 100644 --- a/swizzler.py +++ b/swizzler.py @@ -67,11 +67,13 @@ class SwizzlerApp(object): conf = cherrypy.request.app.config['swizzler'] twister = Twister(conf['rpc_url'],format_twist) user = twister.get_user_info(username) + messages = twister.get_user_posts(username,conf['num_messages']) result = { 'is_user':True, - 'title':u"{0} (@{1}): Profile - Swizzler".format(user['fullname'],user['username']), + 'title':u"{fullname} (@{username}): Profile - Swizzler".format(**user), 'subject':user, - 'messages':twister.get_user_posts(username,conf['num_messages']), + 'messages':messages, + 'any_messages':not not messages, 'local_users':twister.local_user_menu()['users'], 'info':twister.get_info(), #the filter avoids some utf etc. that ttf can't handle (TODO: fix or replace format_twist) @@ -82,11 +84,13 @@ class SwizzlerApp(object): def tag(self,tag): conf = cherrypy.request.app.config['swizzler'] twister = Twister(conf['rpc_url'],format_twist) + messages = twister.get_tag_posts(tag) result = { 'is_tag':True, 'title':u"#{0} - Swizzler".format(tag), 'subject':{"fullname":tag}, - 'messages':twister.get_tag_posts(tag), + 'messages':messages, + 'any_messages':not not messages, 'local_users':twister.local_user_menu()['users'], 'info':twister.get_info(), #the filter avoids some utf etc. that ttf can't handle (TODO: fix or replace format_twist) @@ -106,19 +110,42 @@ class SwizzlerApp(object): 'is_home':True, 'is_mentions':mode=='mentions', 'is_feed':mode!='mentions', - 'title':u"{0} (@{1}): Home - Swizzler".format(menu['active']['fullname'],menu['active']['username']), + 'title':u"{fullname} (@{username}): Home - Swizzler".format(**menu['active']), 'local_users':menu['users'], 'info':twister.get_info(), 'subject':menu['active'], 'messages':messages, + 'any_messages':not not messages, #the filter avoids some utf etc. that ttf can't handle (TODO: fix or replace format_twist) 'trending':format_trending(twister,conf['num_messages']) } return stache.render(stache.load_template('standard'),result) @cherrypy.expose + def messages(self,localusername,remoteusername=None): + conf = cherrypy.request.app.config['swizzler'] + twister = Twister(conf['rpc_url'],format_twist) + localuser = twister.get_user_info(localusername) + remoteuser = remoteusername and twister.get_user_info(remoteusername) or None + threads = remoteusername and twister.get_user_messages(localusername,remoteusername,conf['num_messages']) or twister.get_user_messages(localusername) + result = { + 'title':u"{0} (@{1}): direct messages{2}".format( + localuser['fullname'],localuser['username'], + remoteuser and u" with {fullname} (@{username}) - Swizzler".format(**remoteuser) or ""), + 'subject':localuser, + 'remoteuser':remoteuser, + 'threads':threads, + 'any_threads':not not threads, + 'local_users':twister.local_user_menu()['users'], + 'info':twister.get_info(), + #the filter avoids some utf etc. that ttf can't handle (TODO: fix or replace format_twist) + 'trending':format_trending(twister,conf['num_messages']) + } + return stache.render(stache.load_template('messages'),result) + @cherrypy.expose def index(self): conf = cherrypy.request.app.config['swizzler'] twister = Twister(conf['rpc_url'],format_twist) + messages = twister.get_sponsored_posts(conf['num_messages']) result = { 'is_user':True, # i.e. we want to display "bio" and not mentions/DMs/profile buttons 'title':"Welcome to Swizzler", @@ -133,7 +160,8 @@ Instead, they enjoy occasional minutes of fame in the form of the sponsored post We #Respect their hard earned crypto-graffiti by appreciating them on coffee/spliff/soy-milk/etc. breaks, because that's how we roll yo. Start mining today, and all this (AND moral satisfaction) can be yours.""") }, - 'messages':twister.get_sponsored_posts(conf['num_messages']), + 'messages':messages, + 'any_messages':not not messages, #the filter avoids some utf etc. that ttf can't handle (TODO: fix or replace format_twist) 'trending':format_trending(twister,conf['num_messages']) } diff --git a/templates/message.html b/templates/message.html index 5015e69..9e862ec 100644 --- a/templates/message.html +++ b/templates/message.html @@ -1,7 +1,7 @@
  • {{#user}} {{#username}} - + {{fullname}} {{/username}} diff --git a/templates/messages.html b/templates/messages.html new file mode 100644 index 0000000..7e46be9 --- /dev/null +++ b/templates/messages.html @@ -0,0 +1,92 @@ + + + + + + + {{title}} + + + + + + +
    +
    +
    +
    + +
    +
    +
    + {{#any_threads}} +
      + {{#threads}} + {{^remoteuser}} + {{#user}} +
      + {{fullname}} + +
      + {{/user}} + {{/remoteuser}} + {{#remoteuser}} + {{#subject}} +
      + + Back +
      + {{/subject}} + {{/remoteuser}} +
        + {{#messages}} + {{> message}} + {{/messages}} +
      + {{/threads}} +
    + {{/any_threads}} + + {{^threads}} +

    Nothing. Nada. Rien de rien. 😭

    + {{/threads}} +
    +
    +
    + +
    + {{> footer}} +
    + + + diff --git a/templates/standard.html b/templates/standard.html index 86adad0..dc734b1 100644 --- a/templates/standard.html +++ b/templates/standard.html @@ -29,10 +29,10 @@ {{fullname}} {{/is_feed}} {{#is_mentions}} - {{fullname}} + {{fullname}} {{/is_mentions}} {{#is_messages}} - {{fullname}} + {{fullname}} {{/is_messages}} {{^is_feed}} @@ -67,7 +67,7 @@
    - {{#messages}}
      {{> message}}
    {{/messages}} + {{#any_messages}}
      {{#messages}}{{> message}}{{/messages}}
    {{/any_messages}} {{^messages}}

    Nothing. Nada. Rien de rien. 😭

    {{/messages}} diff --git a/twister.py b/twister.py index ed75614..ab24bfc 100644 --- a/twister.py +++ b/twister.py @@ -110,6 +110,28 @@ class Twister: def get_user_mentions(self,localusername): return [self._format_post_info(p['p']['v']) for p in self.twister.dhtget(localusername,'mention','m')] @functioncache(60,ignore_instance=True) + def get_user_messages(self,localusername,username=None,num=2): + if username: + raw = self.twister.getdirectmsgs(localusername,num,[{"username":username}]) + else: + raw = self.twister.getdirectmsgs(localusername,num,self.get_following(localusername)) + result =[] + localuser = self.get_user_info(localusername) + for username in raw: + user = self.get_user_info(username) + messages = [] + latest_ts = 0 + for message in raw[username]: + if message['time'] > latest_ts: + latest_ts = message['time'] + message['time'] = timestamp2iso(message['time']) + message['user'] = message['fromMe'] and localuser or user + message['message'] = self._format_message(message['text']) + messages.insert(0,message) # reverse order (newer first) + result.append({'user':user,'messages':messages,'latest_ts':latest_ts}) + return sorted(result,key=lambda thread:thread['latest_ts'],reverse=True) + + @functioncache(60,ignore_instance=True) def get_user_posts(self,username,num=8): result = [self._format_post_info(p) for p in self.twister.getposts(num,[{'username':username}])] if result: