├── LICENSE ├── __init__.py ├── app ├── controllers │ ├── __init__.py │ ├── forms.py │ ├── stars.py │ ├── auth.py │ ├── indexer.py │ └── routes.py ├── models │ ├── __init__.py │ └── tables.py ├── static │ ├── images │ │ ├── logo.png │ │ ├── favicon.ico │ │ └── Delta-logo.png │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ ├── CWB0XYA8bzo0kSThX0UTuA.woff2 │ │ ├── DXI1ORHCpsQm3Vp6mXoaTegdm0LZdjqr5-oayXSOefg.woff2 │ │ ├── Q_Z9mv4hySLTMoMjnk_rCfesZW2xOQ-xsNqO47m55DA.woff2 │ │ ├── cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2 │ │ └── d-6IYplOFocCacKzxwXSOFtXRa8TVwTICgirnJhmVJw.woff2 │ ├── css │ │ ├── custom.css │ │ ├── fonts.css │ │ └── font-awesome.min.css │ └── js │ │ ├── custom.js │ │ ├── CircularLoader.js │ │ └── jquery.js ├── templates │ ├── file.html │ ├── semester.html │ ├── home.html │ ├── login.html │ ├── upload.html │ ├── faq.html │ ├── notes.html │ └── base.html ├── __init__.py ├── settings.py └── utils.py ├── run.py ├── bani.sh ├── index.py ├── requirements.txt ├── manager.py ├── .gitignore └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/__init__.py: -------------------------------------------------------------------------------- 1 | from tables import * 2 | -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | from app import app 2 | if __name__ == '__main__': 3 | app.run(debug=True) 4 | -------------------------------------------------------------------------------- /app/static/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/images/logo.png -------------------------------------------------------------------------------- /app/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/images/favicon.ico -------------------------------------------------------------------------------- /app/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /app/static/images/Delta-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/images/Delta-logo.png -------------------------------------------------------------------------------- /bani.sh: -------------------------------------------------------------------------------- 1 | curl "http://0.0.0.0:8983/solr/update?stream.body=%3Cdelete%3E%3Cquery%3E*:*%3C/query%3E%3C/delete%3E&commit=true" 2 | -------------------------------------------------------------------------------- /app/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /app/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /app/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /app/static/fonts/CWB0XYA8bzo0kSThX0UTuA.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/CWB0XYA8bzo0kSThX0UTuA.woff2 -------------------------------------------------------------------------------- /app/static/fonts/DXI1ORHCpsQm3Vp6mXoaTegdm0LZdjqr5-oayXSOefg.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/DXI1ORHCpsQm3Vp6mXoaTegdm0LZdjqr5-oayXSOefg.woff2 -------------------------------------------------------------------------------- /app/static/fonts/Q_Z9mv4hySLTMoMjnk_rCfesZW2xOQ-xsNqO47m55DA.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/Q_Z9mv4hySLTMoMjnk_rCfesZW2xOQ-xsNqO47m55DA.woff2 -------------------------------------------------------------------------------- /app/static/fonts/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2 -------------------------------------------------------------------------------- /app/static/fonts/d-6IYplOFocCacKzxwXSOFtXRa8TVwTICgirnJhmVJw.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delta/NotesSharing/HEAD/app/static/fonts/d-6IYplOFocCacKzxwXSOFtXRa8TVwTICgirnJhmVJw.woff2 -------------------------------------------------------------------------------- /index.py: -------------------------------------------------------------------------------- 1 | import urllib 2 | import pycurl 3 | import requests 4 | c= pycurl.Curl() 5 | requests.post("http://localhost:8983/solr/firenotes/update/extract?literal.id=Ch6_STLAssociativeContainersAndIterators.pdf&commit=true -F myfile=@/home/nirvik/Dev/code/FLASK_APPS/fireNotes/app/controllers/../../tmp/Ch6_STLAssociativeContainersAndIterators.pdf") 6 | #c.setopt(c.URL,s) 7 | #c.perform() 8 | print c 9 | -------------------------------------------------------------------------------- /app/templates/file.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 | 4 |
5 | 6 | 9 |

Welcome to {{dept}}

10 |
11 | {% for information in file %} 12 | {% endfor %} 13 | 14 |
15 | 16 | 23 | 24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /app/templates/semester.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 | 4 |
5 | 6 | 7 | 10 |

Welcome to {{dept}} !

11 |
12 | {% for sem in semesters %} 13 | Semester {{sem}} 14 | {% endfor %} 15 | 16 |
17 | 24 | 25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Babel==1.3 2 | Flask==0.10.1 3 | Flask-Babel==0.9 4 | Flask-Login==0.2.11 5 | Flask-Mail==0.9.1 6 | Flask-SQLAlchemy==2.0 7 | Flask-WTF==0.11 8 | Flask-WhooshAlchemy==0.56 9 | Jinja2==2.7.3 10 | MarkupSafe==0.23 11 | SQLAlchemy==0.7.9 12 | Tempita==0.5.2 13 | WTForms==2.0.2 14 | Werkzeug==0.10.1 15 | Whoosh==2.6.0 16 | argparse==1.2.1 17 | blinker==1.3 18 | decorator==3.4.0 19 | flup==1.0.2 20 | itsdangerous==0.24 21 | pbr==0.10.8 22 | pytz==2013b 23 | six==1.9.0 24 | speaklater==1.3 25 | sqlalchemy-migrate==0.9.5 26 | sqlparse==0.1.14 27 | wsgiref==0.1.2 28 | Flask-Migrate 29 | gunicorn 30 | reportlab 31 | requests 32 | celery 33 | redis 34 | 35 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | import flask 2 | from flask.ext.sqlalchemy import SQLAlchemy 3 | import os 4 | from flask.ext.login import LoginManager 5 | # We also need to initialize our database 6 | 7 | 8 | app = flask.Flask(__name__) # Our Flask instance 9 | db = SQLAlchemy(app) 10 | 11 | env = os.environ.get('FIRENOTES_ENV','dev') 12 | app.config.from_object('app.settings.%sConfig' % env.capitalize()) 13 | app.config['ENV'] = env 14 | lm = LoginManager() 15 | lm.init_app(app) 16 | 17 | 18 | #print app.config 19 | # We are setting our environment to development 20 | import flask.ext.whooshalchemy as whooshalchemy 21 | from controllers import routes 22 | import models 23 | 24 | whooshalchemy.whoosh_index(app, models.files) 25 | -------------------------------------------------------------------------------- /app/controllers/forms.py: -------------------------------------------------------------------------------- 1 | from flask.ext.wtf import Form 2 | from wtforms import StringField, BooleanField, PasswordField 3 | from wtforms.validators import DataRequired 4 | 5 | 6 | class LoginForm(Form): 7 | # DataRequired checks if the field is not left empty 8 | rollnumber = StringField('Roll Number', validators=[DataRequired()]) 9 | password = PasswordField('New Password', validators=[DataRequired()]) 10 | # remember_me = BooleanField('remember me', default = False) 11 | 12 | 13 | 14 | class MetaData(Form): 15 | author = StringField('Author of notes',validators=[DataRequired()]) 16 | tags = StringField('Enter tags',validators=[DataRequired()]) 17 | description = StringField('Enter description', validators =[DataRequired()]) 18 | 19 | class Search(Form): 20 | query = StringField('Search whatever you want') 21 | 22 | -------------------------------------------------------------------------------- /app/templates/home.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 | 4 |
5 | {% if g.user.is_authenticated() %} 6 |

Welcome

7 | {% endif %} 8 |
9 |
10 | {% for dept in x %} 11 | {{dept}} 12 | {% endfor %} 13 | 14 |
15 | 16 |
17 | 24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /app/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | class Config(object): 3 | SECRET_KEY = 'HAHAHAH-FUCK-YOU' 4 | basedir = os.path.abspath(os.path.dirname(__file__)) 5 | WTF_CSRF_ENABLED = True 6 | UPLOAD_FOLDER = basedir + '/../tmp' 7 | ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif','odp','pptx','docx','doc','ppt','rtf','odt']) 8 | IMAP_SERVER = 'webmail.nitt.edu' 9 | IMAP_SERVER_PORT = '143' 10 | WHOOSH_BASE = os.path.join(basedir, 'search.db') #A special database that is dedicated to full text search 11 | CELERY_BROKER_URL = 'redis://localhost:6379/0' 12 | CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' 13 | DEBUG = True 14 | class DevConfig(Config): 15 | DEBUG = False 16 | SQLALCHEMY_DATABASE_URI = 'mysql+mysqldb://notes:thisisacomplexpassword@localhost/firenotes' 17 | #'sqlite:///../app.db' + '?check_same_thread=False' 18 | 19 | 20 | class ProdConfig(Config): 21 | pass 22 | -------------------------------------------------------------------------------- /app/static/css/custom.css: -------------------------------------------------------------------------------- 1 | h1 , h2 { 2 | text-align : center ; 3 | font: 80px 'Pacifico', Helvetica, sans-serif; 4 | color: #2b2b2b; 5 | text-shadow: 3px 3px 0px rgba(0,0,0,0.1), 7px 7px 0px rgba(0,0,0,0.05); 6 | margin-bottom: -60px; 7 | } 8 | footer { 9 | font-size: 12px; 10 | position:relative; 11 | left:0px; 12 | bottom:10px; 13 | width:100%; 14 | margin-top:80px; 15 | } 16 | #footy { 17 | font-size: 12px; 18 | position:relative; 19 | left:0px; 20 | bottom:10px; 21 | width:100%; 22 | } 23 | .table tr { 24 | text-align: left; 25 | } 26 | #yourBtn{ 27 | position: relative; 28 | top: 150px; 29 | font-family: calibri; 30 | width: 150px; 31 | padding: 10px; 32 | -webkit-border-radius: 5px; 33 | -moz-border-radius: 5px; 34 | border: 1px dashed #BBB; 35 | text-align: center; 36 | background-color: #DDD; 37 | cursor:pointer; 38 | } 39 | -------------------------------------------------------------------------------- /manager.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from flask.ext.script import Manager , Shell, Server 3 | from flask.ext.migrate import Migrate, MigrateCommand 4 | from app import app, db, models 5 | from app.utils import GunicornServer 6 | import os 7 | 8 | migrate = Migrate(app, db) 9 | 10 | manager = Manager(app) 11 | manager.add_command('runserver',Server(port=5000,host="0.0.0.0"),debug=True) 12 | manager.add_command('shell',Shell()) 13 | manager.add_command('gunicorn', GunicornServer(app)) 14 | manager.add_command('db',MigrateCommand) 15 | @manager.command 16 | def create_db(): 17 | db.create_all() 18 | depts = ['CSE', 'EEE', 'ECE', 'MECH', 'PROD', 'ICE', 'META', 'CIVIL', 'ARCHI', 'CHEM'] 19 | for dept in depts : 20 | entry = models.Department(department = dept) 21 | db.session.add(entry) 22 | db.session.commit() 23 | 24 | 25 | @manager.command 26 | def delete_db(): 27 | db.drop_all() 28 | 29 | manager.run() 30 | -------------------------------------------------------------------------------- /app/static/css/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Roboto'; 3 | font-style: normal; 4 | font-weight: 300; 5 | src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v15/Hgo13k-tfSpn0qi1SFdUfVtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); 6 | } 7 | @font-face { 8 | font-family: 'Roboto'; 9 | font-style: normal; 10 | font-weight: 400; 11 | src: local('Roboto'), local('Roboto-Regular'), url(../fonts/CWB0XYA8bzo0kSThX0UTuA.woff2) format('woff2'); 12 | } 13 | @font-face { 14 | font-family: 'Roboto'; 15 | font-style: normal; 16 | font-weight: 500; 17 | src: local('Roboto Medium'), local('Roboto-Medium'), url(http://fonts.gstatic.com/s/roboto/v15/RxZJdnzeo3R5zSexge8UUVtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); 18 | } 19 | @font-face { 20 | font-family: 'Roboto'; 21 | font-style: normal; 22 | font-weight: 700; 23 | src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/d-6IYplOFocCacKzxwXSOFtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); 24 | } 25 | -------------------------------------------------------------------------------- /app/controllers/stars.py: -------------------------------------------------------------------------------- 1 | from ..models import * 2 | from app import app, db # Your init files 3 | from sqlalchemy import or_, and_ 4 | 5 | 6 | def add_star(file_id, user_rno): 7 | starred_file = stars(file_id=file_id, starrer=user_rno) 8 | db.session.add(starred_file) 9 | db.session.commit() 10 | 11 | def reduce_star(file_id,user_rno): 12 | starred_file = stars.query.filter(and_(stars.file_id.like(file_id),stars.starrer.like(user_rno))).all() 13 | for remove_file in starred_file: 14 | db.session.delete(remove_file) 15 | db.session.commit() 16 | 17 | def get_stars(file_id): 18 | all_stars = stars.query.with_entities(stars.starrer).filter(stars.file_id.like(file_id)).distinct() 19 | return len(list(all_stars)) 20 | 21 | def has_starred(file_id, user_rno): 22 | starred = stars.query.filter(and_(stars.file_id.like(file_id), 23 | stars.starrer.like(user_rno))).all() 24 | return len(starred) >= 1 25 | 26 | if __name__=='__main__': 27 | print has_starred(1, '106112091') 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rdb 2 | migrations/ 3 | /whoosh_index 4 | /search.db 5 | *.pyc 6 | *.db* 7 | /db_repository 8 | *.pdf 9 | **/*.pyc 10 | tmp 11 | *~ 12 | **/*~ 13 | # Byte-compiled / optimized / DLL files 14 | __pycache__/ 15 | *.py[cod] 16 | 17 | # C extensions 18 | *.so 19 | 20 | # Distribution / packaging 21 | .Python 22 | env/ 23 | build/ 24 | develop-eggs/ 25 | dist/ 26 | downloads/ 27 | eggs/ 28 | .eggs/ 29 | lib/ 30 | lib64/ 31 | parts/ 32 | sdist/ 33 | var/ 34 | *.egg-info/ 35 | .installed.cfg 36 | *.egg 37 | 38 | # PyInstaller 39 | # Usually these files are written by a python script from a template 40 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 41 | *.manifest 42 | *.spec 43 | 44 | # Installer logs 45 | pip-log.txt 46 | pip-delete-this-directory.txt 47 | 48 | # Unit test / coverage reports 49 | htmlcov/ 50 | .tox/ 51 | .coverage 52 | .coverage.* 53 | .cache 54 | nosetests.xml 55 | coverage.xml 56 | *,cover 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | -------------------------------------------------------------------------------- /app/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 |
7 | {{ form.hidden_tag() }} 8 | {{ message }} 9 |
10 | {{ form.rollnumber(size=9,class="form-control",placeholder="Enter roll number") }} 11 | {% for error in form.rollnumber.errors %} 12 | [ {{ error }} ] 13 | {% endfor %} 14 |
15 | 16 |
17 | {{ form.password(size=9,class="form-control", placeholder="Webmail Password")}} 18 | {% for error in form.password.errors %} 19 | [ {{ error }} ] 20 | {% endfor %} 21 |
22 | 25 |
26 |
27 |
28 |
29 |
30 | 37 | {% endblock %} 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![alt text](./app/static/images/logo.png "Fire Notes") 2 | 3 | Fire Notes is a notes sharing platform where students can upload, maintain versions and download notes. 4 | 5 | ##To do 6 | - [x] Add apache solr for document search 7 | - [x] Add Star feature 8 | - [x] Add Download Counter 9 | - [x] Add Meta Data before uploading file 10 | - [x] Search files by metadata 11 | - [ ] Add subjects of each semester to database 12 | - [ ] Subjects Scraper 13 | - [x] Concatenate the files into a single pdf 14 | - [x] Upload multiple files at once 15 | 16 | ##How to run 17 | * drop all db 18 | * delete app.db 19 | * delete search.db (Whoosh index) 20 | * delete migration folder 21 | * start redis-server 22 | * initiate apache solr -> ./bin/solr start -e cloud -noprompt 23 | ```py 24 | python manager.py create_db 25 | python manager.py db init 26 | python manager.py gunicorn 27 | ``` 28 | 29 | ##Features 30 | * Upload and download notes. 31 | * Anybody can download any version of the file. 32 | * People can upload notes only to the deparment they belong to. 33 | 34 | ##Contribute 35 | If you want to add features, fix bugs, or report issues, feel free to send a pull request!! 36 | 37 | ####Contributors 38 | * Nirvik Ghosh 39 | * Sriram S 40 | * Anantha Natarajan 41 | * Vignesh Manix 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/static/js/custom.js: -------------------------------------------------------------------------------- 1 | function starrer(fid, rno){ 2 | if(document.getElementById("starclass"+fid).className !="fa fa-star fa-2x") { 3 | console.log(String(fid)); 4 | request = $.ajax({ 5 | url: ".", 6 | type: "post", 7 | data: { 8 | star: "1", 9 | file_id: String(fid), 10 | user_rno: rno, 11 | } 12 | }); 13 | request.done(function (response, textStatus, jqXHR){ 14 | console.log(response); 15 | document.getElementById("starclass"+fid).className="fa fa-star fa-2x"; 16 | down_count = parseInt(document.getElementsByName("count"+fid)[0].innerHTML)+1; 17 | document.getElementsByName("count"+fid)[0].innerHTML = down_count; 18 | 19 | }); 20 | } 21 | else if ( document.getElementById("starclass"+fid).className == "fa fa-star fa-2x"){ 22 | console.log(String(fid)); 23 | request = $.ajax({ 24 | url : ".", 25 | type : "post", 26 | data : { 27 | star : "-1", 28 | file_id : String(fid), 29 | user_rno : rno, 30 | } 31 | }); 32 | 33 | request.done(function (response, textStatus, jqXHR){ 34 | console.log(response); 35 | document.getElementById("starclass"+fid).className="fa fa-star-o fa-2x"; 36 | down_count = parseInt(document.getElementsByName("count"+fid)[0].innerHTML)-1; 37 | document.getElementsByName("count"+fid)[0].innerHTML = down_count; 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/templates/upload.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 | 9 | 10 |
11 |

Upload Notes, Books et al.

12 | {% if g.user.is_authenticated() and g.user.dept==dept %} 13 | 14 |
15 | {{ form.hidden_tag() }} 16 | {{ message }} 17 |
18 | {{ form.author(size=20,class="form-control",placeholder="Enter author") }} 19 | {{ form.tags(size=20,class="form-control", placeholder = "CT1,CT2,SEM")}} 20 | {{ form.description(size=100,class="form-control",placeholder="Enter Name of subject (or description)") }} 21 |
22 | 23 |
24 |
25 | 26 | 27 |
28 | 29 | 30 |
31 |
32 |
33 |