From fd39e64f6bd2e94b8b19263ebdc329a38b7c2f85 Mon Sep 17 00:00:00 2001 From: Ciana Lim Date: Mon, 9 Nov 2015 17:31:56 +0800 Subject: [PATCH] first commit --- .DS_Store | Bin 0 -> 6148 bytes .gitignore | 1 + LICENSE | 33 ++++++++ Procfile | 1 + README.md | 6 ++ __init__.py | 0 controllers/.DS_Store | Bin 0 -> 6148 bytes controllers/__init__.py | 0 controllers/follow.py | 33 ++++++++ controllers/timeline.py | 48 +++++++++++ controllers/tweet.py | 17 ++++ controllers/user.py | 57 +++++++++++++ csitwit.py | 22 +++++ helpers/.DS_Store | Bin 0 -> 6148 bytes helpers/__init__.py | 0 helpers/functions.py | 64 +++++++++++++++ helpers/init.py | 14 ++++ minitwit.db | Bin 0 -> 5120 bytes requirements.txt | 8 ++ router.py | 33 ++++++++ schema.sql | 23 ++++++ static/style.css | 178 ++++++++++++++++++++++++++++++++++++++++ templates/.DS_Store | Bin 0 -> 6148 bytes templates/layout.html | 32 ++++++++ templates/login.html | 16 ++++ templates/register.html | 20 +++++ templates/timeline.html | 48 +++++++++++ 27 files changed, 654 insertions(+) create mode 100644 .DS_Store create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Procfile create mode 100644 README.md create mode 100644 __init__.py create mode 100644 controllers/.DS_Store create mode 100644 controllers/__init__.py create mode 100644 controllers/follow.py create mode 100644 controllers/timeline.py create mode 100644 controllers/tweet.py create mode 100644 controllers/user.py create mode 100644 csitwit.py create mode 100644 helpers/.DS_Store create mode 100644 helpers/__init__.py create mode 100644 helpers/functions.py create mode 100644 helpers/init.py create mode 100644 minitwit.db create mode 100644 requirements.txt create mode 100644 router.py create mode 100644 schema.sql create mode 100644 static/style.css create mode 100644 templates/.DS_Store create mode 100644 templates/layout.html create mode 100644 templates/login.html create mode 100644 templates/register.html create mode 100644 templates/timeline.html diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3758a582f113bb8ec5f64a4ea2b86ec24f6c68eb GIT binary patch literal 6148 zcmeHK%TB{U3>-rRMZNUMaesk7h^q1h`~Z+f0%;+rfqQQJHsc4-DCNqbvMYPCUeBhP zLmUH;&ByKrSOZwn74fNIZo02Nv$M!7h+=2#(WCO$VLz)ro>1-zEqSkaC+n9#?1r{J z_I*|2C7yU_#hV>H*}A|$<^%m1?IGuisSYpXRNL+_;T``!nN0;!fm9$BNCi$^0rqUQ z<;pQ*Dv%1K0zV4q`=QVko50c0UL6cJ0uc2x-i+5aOAw1Dh)v+=$P7)KN_48kh#^jA zzC>LUI668V62phYoh2p|vAgs9V&#y=F=Hx_3QQF^_vKpq|1JHG`F~2vRVt7QoRk8x z*xqe7e5B~Dvxn1OTj=-nZ)2^MGgvDoS}W#4Tk-WlUD0dqH-V$0(U~_oF+T)Um$X#i HKNR=^MnEXf literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed8ebf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a7da10e --- /dev/null +++ b/LICENSE @@ -0,0 +1,33 @@ +Copyright (c) 2015 by Armin Ronacher and contributors. See AUTHORS +for more details. + +Some rights reserved. + +Redistribution and use in source and binary forms of the software as well +as documentation, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +* The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..9bde38a --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: gunicorn csitwit:app --log-file=- diff --git a/README.md b/README.md new file mode 100644 index 0000000..b4b47c3 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +export MINITWIT_SETTINGS env var or edit minitwit.py + +python3 -m flask -a csitwit initdb +python3 csitwit.py + +This is a modification of the MiniTwit example from Flask. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/controllers/.DS_Store b/controllers/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T07*%la|%PksJs(Eoq_kA%Vqo}0EL3J^;qg*J zOpp02j!9>%axbSp2inUE4Us+m$??<8ILyz}GJ7$MH7Fg`kDVj=j$+;L1 zpDpt%YeNYZDl;?icwrQ?7qciG!qn9%GAc1OCJMTl&UA5_=PGH;C$4uD?)KXbiJfUj zv3A~@M*w|6uZ1(==oW3vtdzUY02A|IK^~TUMhEF5D4+w+^(~hKq&Xl?7(TN?ziS>) zTUm`ABCpCAx%KS*k{vVl=Rc@?egq z8OI*$8*(&UqICw{dR5kJo5*!)Q{146p~!}5D0QsYIOD#9>dU7Ma8mdQmU@VjMWKcvch40E10Qi{|o2` zK)?8uNyb3Nz};k^B%oP%@dAhLK{Nx?R|qlfe~5kqeq@p{kTLMTFpz@?LUHtMj?g!N zexmPOWs)(FG4KyEP(e8WAB&>H_%D%VsUJojo!?tKIejQ_M@2*q;SLTg+=m<}bHLqO H`+E8ZvbaWO literal 0 HcmV?d00001 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fa15648 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +click==5.1 +-e git://github.com/mitsuhiko/flask.git#egg=Flask +gunicorn==19.3.0 +itsdangerous==0.24 +Jinja2==2.8 +MarkupSafe==0.23 +Werkzeug==0.10.4 +wheel==0.24.0 diff --git a/router.py b/router.py new file mode 100644 index 0000000..35f830b --- /dev/null +++ b/router.py @@ -0,0 +1,33 @@ +from flask import g, session +from helpers import functions, init +from controllers import follow, timeline, tweet, user + +def set_router(app): + # we're setting g.user as the user in the current session + @app.before_request + def before_request(): + g.user = None + if 'user_id' in session: + # if there is a user_id in session + # select it and set g.user to it + g.user = functions.query_db('select * from user where user_id = ?', + [session['user_id']], one=True) + + ### Our Routes ### + + # timeline routes + app.route('/')(timeline.index) + app.route('/public')(timeline.public) + app.route('/')(timeline.user) + + # follow routes + app.route('//follow')(follow.follow_user) + app.route('//unfollow')(follow.unfollow_user) + + # tweet routes + app.route('/add_message', methods=['POST'])(tweet.add_message) + + # user routes + app.route('/login', methods=['GET', 'POST'])(user.login) + app.route('/register', methods=['GET', 'POST'])(user.register) + app.route('/logout')(user.logout) diff --git a/schema.sql b/schema.sql new file mode 100644 index 0000000..d2fdba2 --- /dev/null +++ b/schema.sql @@ -0,0 +1,23 @@ +drop table if exists user; +create table user ( + user_id integer primary key autoincrement, + username text not null, + email text not null, + pw_hash text not null +); + +drop table if exists follower; +create table follower ( + who_id integer, + whom_id integer +); + +drop table if exists message; +create table message ( + message_id integer primary key autoincrement, + author_id integer not null, + text text not null, + pub_date integer +); + +INSERT INTO user (username, email, pw_hash) VALUES ('person', 'person@gmail.com', 'pbkdf2:sha1:1000$L1UfsRgW$d780bf74e8432301bbdd361ee5ade12e842820e3') diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..49a39d8 --- /dev/null +++ b/static/style.css @@ -0,0 +1,178 @@ +body { + background: #BEE8E4; + font-family: 'Trebuchet MS', sans-serif; + font-size: 14px; +} + +a { + color: #26776F; +} + +a:hover { + color: #333; +} + +input[type="text"], +input[type="password"] { + background: white; + border: 1px solid #BFE6E2; + padding: 2px; + font-family: 'Trebuchet MS', sans-serif; + font-size: 14px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + color: #105751; +} + +input[type="submit"] { + background: #105751; + border: 1px solid #073B36; + padding: 1px 3px; + font-family: 'Trebuchet MS', sans-serif; + font-size: 14px; + font-weight: bold; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + color: white; +} + +div.page { + background: white; + border: 1px solid #6ECCC4; + width: 700px; + margin: 30px auto; +} + +div.page h1 { + background: #6ECCC4; + margin: 0; + padding: 10px 14px; + color: white; + letter-spacing: 1px; + text-shadow: 0 0 3px #24776F; + font-weight: normal; +} + +div.page div.navigation { + background: #DEE9E8; + padding: 4px 10px; + border-top: 1px solid #ccc; + border-bottom: 1px solid #eee; + color: #888; + font-size: 12px; + letter-spacing: 0.5px; +} + +div.page div.navigation a { + color: #444; + font-weight: bold; +} + +div.page h2 { + margin: 0 0 15px 0; + color: #105751; + text-shadow: 0 1px 2px #ccc; +} + +div.page div.body { + padding: 10px; +} + +div.page div.footer { + background: #eee; + color: #888; + padding: 5px 10px; + font-size: 12px; +} + +div.page div.followstatus { + border: 1px solid #ccc; + background: #E3EBEA; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + padding: 3px; + font-size: 13px; +} + +div.page ul.messages { + list-style: none; + margin: 0; + padding: 0; +} + +div.page ul.messages li { + margin: 10px 0; + padding: 5px; + background: #F0FAF9; + border: 1px solid #DBF3F1; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + min-height: 48px; +} + +div.page ul.messages p { + margin: 0; +} + +div.page ul.messages li img { + float: left; + padding: 0 10px 0 0; +} + +div.page ul.messages li small { + font-size: 0.9em; + color: #888; +} + +div.page div.twitbox { + margin: 10px 0; + padding: 5px; + background: #F0FAF9; + border: 1px solid #94E2DA; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +div.page div.twitbox h3 { + margin: 0; + font-size: 1em; + color: #2C7E76; +} + +div.page div.twitbox p { + margin: 0; +} + +div.page div.twitbox input[type="text"] { + width: 585px; +} + +div.page div.twitbox input[type="submit"] { + width: 70px; + margin-left: 5px; +} + +ul.flashes { + list-style: none; + margin: 10px 10px 0 10px; + padding: 0; +} + +ul.flashes li { + background: #B9F3ED; + border: 1px solid #81CEC6; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + padding: 4px; + font-size: 13px; +} + +div.error { + margin: 10px 0; + background: #FAE4E4; + border: 1px solid #DD6F6F; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + padding: 4px; + font-size: 13px; +} diff --git a/templates/.DS_Store b/templates/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 +{% block title %}Welcome{% endblock %} | CSITwit + +
+

CSITwit

+ + {% with flashes = get_flashed_messages() %} + {% if flashes %} +
    + {% for message in flashes %} +
  • {{ message }} + {% endfor %} +
+ {% endif %} + {% endwith %} +
+ {% block body %}{% endblock %} +
+ +
diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..f15bf10 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,16 @@ +{% extends "layout.html" %} +{% block title %}Sign In{% endblock %} +{% block body %} +

Sign In

+ {% if error %}
Error: {{ error }}
{% endif %} +
+
+
Username: +
+
Password: +
+
+
+
+{% endblock %} + diff --git a/templates/register.html b/templates/register.html new file mode 100644 index 0000000..446133c --- /dev/null +++ b/templates/register.html @@ -0,0 +1,20 @@ +{% extends "layout.html" %} +{% block title %}Sign Up{% endblock %} +{% block body %} +

Sign Up

+ {% if error %}
Error: {{ error }}
{% endif %} +
+
+
Username: +
+
E-Mail: +
+
Password: +
+ +
Confirm Password: +
+
+
+
+{% endblock %} diff --git a/templates/timeline.html b/templates/timeline.html new file mode 100644 index 0000000..efc2315 --- /dev/null +++ b/templates/timeline.html @@ -0,0 +1,48 @@ +{% extends "layout.html" %} +{% block title %} + {% if request.endpoint == 'index' %} + Public Timeline + {% elif request.endpoint == 'user' %} + {{ profile_user.username }}'s Timeline + {% else %} + My Timeline + {% endif %} +{% endblock %} +{% block body %} +

{{ self.title() }}

+ {% if g.user %} + {% if request.endpoint == 'user' %} +
+ {% if g.user.user_id == profile_user.user_id %} + This is you! + {% elif followed %} + You are currently following this user. + Unfollow user. + {% else %} + You are not yet following this user. + . + {% endif %} +
+ {% elif request.endpoint == 'index' %} +
+

What's on your mind {{ g.user.username }}?

+ +
+ +
+
+
+ {% endif %} + {% endif %} +
    + {% for message in messages %} +
  • + {{ message.username }} + {{message.text}} + — {{ message.pub_date|datetimeformat }} + {% else %} +

  • There's no message so far. + {% endfor %} + +
+{% endblock %}