From 2d11023378c6369dd7554f4ac4e14d94078aebee Mon Sep 17 00:00:00 2001 From: Ashutosh Das Date: Fri, 26 Feb 2016 11:17:54 +0600 Subject: [PATCH 1/8] deleted flask files --- db/models.py | 14 -------------- hiren.py | 30 ------------------------------ 2 files changed, 44 deletions(-) delete mode 100644 db/models.py delete mode 100644 hiren.py diff --git a/db/models.py b/db/models.py deleted file mode 100644 index 831792b..0000000 --- a/db/models.py +++ /dev/null @@ -1,14 +0,0 @@ -from hiren import db - - -class Content(db.Model): - id = db.Column(db.Integer, primary_key=True) - comments_url = db.Column(db.String(200), unique=True) - - def __init__(self, comments_url): - self.comments_url = comments_url - - def __repr__(self): - return '' % self.comments_url - -db.create_all() \ No newline at end of file diff --git a/hiren.py b/hiren.py deleted file mode 100644 index 68daab4..0000000 --- a/hiren.py +++ /dev/null @@ -1,30 +0,0 @@ -from flask import Flask -from flask_sqlalchemy import SQLAlchemy -from db import models -import os -import json - -SITE_ROOT = os.path.realpath(os.path.dirname(__file__)) - -try: - with open(os.path.join(SITE_ROOT, 'config.local.json')) as f: - JSON_DATA = json.load(f) -except FileNotFoundError: - with open(os.path.join(SITE_ROOT, 'config.json')) as f: - JSON_DATA = json.load(f) - -app = Flask(__name__) -app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://' + JSON_DATA['db_user'] + ':'\ - + JSON_DATA['db_pass'] + '@localhost/' + JSON_DATA['db_name'] -app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -db = SQLAlchemy(app) - - -@app.route('/') -def hello_world(): - row_count = models.Content.query.count() - return "Number of rows: " + str(row_count) - -if __name__ == '__main__': - app.run(debug=os.environ.get('DEBUG', False)) - From bd84f3c844e7f8f44e4c6faacd310e40ab8c11ee Mon Sep 17 00:00:00 2001 From: Ashutosh Das Date: Fri, 26 Feb 2016 11:18:15 +0600 Subject: [PATCH 2/8] added new requiremnets --- requirements.txt | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/requirements.txt b/requirements.txt index 491a0c2..648ace6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,10 @@ +Django==1.9.2 feedparser==5.2.1 -Flask==0.10.1 -Flask-SQLAlchemy==2.1 -itsdangerous==0.24 -Jinja2==2.8 -MarkupSafe==0.23 mysqlclient==1.3.7 oauthlib==1.0.3 requests==2.9.1 requests-oauthlib==0.6.1 six==1.10.0 -SQLAlchemy==1.0.12 tweepy==3.5.0 -Werkzeug==0.11.4 +uWSGI==2.0.12 wheel==0.29.0 -uwsgi==2.0.12 From 6accd75d299860b69e1ef762ac99a05a958b5e3e Mon Sep 17 00:00:00 2001 From: Ashutosh Das Date: Fri, 26 Feb 2016 11:19:24 +0600 Subject: [PATCH 3/8] deleted flask files --- hn/rss.py | 21 --------------------- twitter/api.py | 17 ----------------- 2 files changed, 38 deletions(-) delete mode 100644 hn/rss.py delete mode 100644 twitter/api.py diff --git a/hn/rss.py b/hn/rss.py deleted file mode 100644 index a7ab26c..0000000 --- a/hn/rss.py +++ /dev/null @@ -1,21 +0,0 @@ -import feedparser -from db.models import Content -from hiren import db - - -def rss(): - """ - Call hacker news api - :return: List of posts - """ - feed = [] - bunny = feedparser.parse('https://news.ycombinator.com/rss') - for i in bunny.entries: - duplicate = Content.query.filter_by(comments_url=i.comments).first() - if duplicate is None: - feed.append(i.title_detail.value + ' : ' + i.link + " " + "Comments: " + i.comments) - hiren = Content(i.comments) - db.session.add(hiren) - db.session.commit() - return feed - diff --git a/twitter/api.py b/twitter/api.py deleted file mode 100644 index 519c3bd..0000000 --- a/twitter/api.py +++ /dev/null @@ -1,17 +0,0 @@ -from hiren import JSON_DATA -from hn import rss -import tweepy - - -def api(): - """ - Post status(s) to twitter - """ - auth = tweepy.OAuthHandler(JSON_DATA['consumer_key'], JSON_DATA['consumer_secret']) - auth.set_access_token(JSON_DATA['access_token'], JSON_DATA['access_token_secret']) - api = tweepy.API(auth) - for i in rss.rss(): - api.update_status(i) - - -api() From 54c56bf41cdf8873ee093e067ec9d8d728bc251c Mon Sep 17 00:00:00 2001 From: Ashutosh Das Date: Fri, 26 Feb 2016 11:20:41 +0600 Subject: [PATCH 4/8] added new field --- config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.json b/config.json index 8b7a781..5390583 100644 --- a/config.json +++ b/config.json @@ -5,5 +5,6 @@ "access_token_secret": "", "db_name": "", "db_user": "", - "db_pass": "" + "db_pass": "", + "secret_key": "" } \ No newline at end of file From 5f963c31c3cbd5ee91313d157f2092ced5658bee Mon Sep 17 00:00:00 2001 From: Ashutosh Das Date: Fri, 26 Feb 2016 11:21:29 +0600 Subject: [PATCH 5/8] rewrite to django :smile: --- hiren/__init__.py | 0 hiren/settings.py | 146 ++++++++++++++++++++++++++++++++ hiren/urls.py | 23 +++++ hiren/wsgi.py | 16 ++++ manage.py | 10 +++ news/__init__.py | 0 news/admin.py | 10 +++ news/apps.py | 5 ++ news/hn.py | 23 +++++ news/migrations/0001_initial.py | 24 ++++++ news/migrations/__init__.py | 0 news/models.py | 9 ++ news/tests.py | 3 + news/twitter.py | 23 +++++ news/views.py | 6 ++ 15 files changed, 298 insertions(+) create mode 100644 hiren/__init__.py create mode 100644 hiren/settings.py create mode 100644 hiren/urls.py create mode 100644 hiren/wsgi.py create mode 100755 manage.py create mode 100644 news/__init__.py create mode 100644 news/admin.py create mode 100644 news/apps.py create mode 100644 news/hn.py create mode 100644 news/migrations/0001_initial.py create mode 100644 news/migrations/__init__.py create mode 100644 news/models.py create mode 100644 news/tests.py create mode 100644 news/twitter.py create mode 100644 news/views.py diff --git a/hiren/__init__.py b/hiren/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hiren/settings.py b/hiren/settings.py new file mode 100644 index 0000000..42a0e68 --- /dev/null +++ b/hiren/settings.py @@ -0,0 +1,146 @@ +""" +Django settings for hiren project. + +Generated by 'django-admin startproject' using Django 1.9.2. + +For more information on this file, see +https://docs.djangoproject.com/en/1.9/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.9/ref/settings/ +""" + +import os +import json + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +try: + with open(BASE_DIR + '/' + 'config.local.json') as f: + JSON_DATA = json.load(f) +except FileNotFoundError: + with open(BASE_DIR + '/' + 'config.json') as f: + JSON_DATA = json.load(f) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.environ.get('SECRET_KEY', JSON_DATA['secret_key']) + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = os.environ.get('DEBUG', False) + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'news' +] + +MIDDLEWARE_CLASSES = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'hiren.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'hiren.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.9/ref/settings/#databases + +if 'TRAVIS' in os.environ: + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'travisci', + 'USER': 'postgres', + 'PASSWORD': '', + 'HOST': 'localhost', + 'PORT': '', + } + } +else: + DATABASES = { + 'default': { + 'NAME': JSON_DATA['db_name'], + 'ENGINE': 'django.db.backends.mysql', + 'USER': JSON_DATA['db_user'], + 'PASSWORD': JSON_DATA['db_pass'], + 'HOST': 'localhost', + 'PORT': '', + } + } + + + +# Password validation +# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.9/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'Asia/Dhaka' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.9/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/hiren/urls.py b/hiren/urls.py new file mode 100644 index 0000000..d4ed95a --- /dev/null +++ b/hiren/urls.py @@ -0,0 +1,23 @@ +"""hiren URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.9/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url +from django.contrib import admin +from news.views import index + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'^', index), +] diff --git a/hiren/wsgi.py b/hiren/wsgi.py new file mode 100644 index 0000000..d60722c --- /dev/null +++ b/hiren/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for hiren project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hiren.settings") + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..e8c02d6 --- /dev/null +++ b/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hiren.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/news/__init__.py b/news/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/news/admin.py b/news/admin.py new file mode 100644 index 0000000..806190c --- /dev/null +++ b/news/admin.py @@ -0,0 +1,10 @@ +from django.contrib import admin +from news.models import Bunny +# Register your models here. + + +class AuthorAdmin(admin.ModelAdmin): + list_display = ['id', 'comment_url', 'time'] + ordering = ['id'] + +admin.site.register(Bunny, AuthorAdmin) \ No newline at end of file diff --git a/news/apps.py b/news/apps.py new file mode 100644 index 0000000..5a7b92d --- /dev/null +++ b/news/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class NewsConfig(AppConfig): + name = 'news' diff --git a/news/hn.py b/news/hn.py new file mode 100644 index 0000000..6720046 --- /dev/null +++ b/news/hn.py @@ -0,0 +1,23 @@ +import feedparser +import django +import os + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hiren.settings") +django.setup() + +from news.models import Bunny + + +def rss(): + """ + Call hacker news api + :return: List of posts + """ + feed = [] + bunny = feedparser.parse('https://news.ycombinator.com/rss') + for i in bunny.entries: + duplicate = Bunny.objects.filter(comment_url=i.comments) + if duplicate.exists() is False: + feed.append(i.title_detail.value + ' : ' + i.link + " " + "Comments: " + i.comments) + Bunny(comment_url=i.comments).save() + return feed diff --git a/news/migrations/0001_initial.py b/news/migrations/0001_initial.py new file mode 100644 index 0000000..4d2221a --- /dev/null +++ b/news/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-26 04:08 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Bunny', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('comment_url', models.URLField(unique=True)), + ('time', models.DateTimeField(auto_now_add=True)), + ], + ), + ] diff --git a/news/migrations/__init__.py b/news/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/news/models.py b/news/models.py new file mode 100644 index 0000000..24b49f0 --- /dev/null +++ b/news/models.py @@ -0,0 +1,9 @@ +from django.db import models + + +class Bunny(models.Model): + comment_url = models.URLField(unique=True) + time = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return 'Comment={0}, Date={1}'.format(self.comment_url, self.time) diff --git a/news/tests.py b/news/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/news/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/news/twitter.py b/news/twitter.py new file mode 100644 index 0000000..9d9e5a0 --- /dev/null +++ b/news/twitter.py @@ -0,0 +1,23 @@ +import django +import os + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hiren.settings") +django.setup() + +from hiren.settings import JSON_DATA +from hn import rss +import tweepy + + +def api(): + """ + Post status(s) to twitter + """ + auth = tweepy.OAuthHandler(JSON_DATA['consumer_key'], JSON_DATA['consumer_secret']) + auth.set_access_token(JSON_DATA['access_token'], JSON_DATA['access_token_secret']) + api = tweepy.API(auth) + for i in rss.rss(): + api.update_status(i) + + +api() diff --git a/news/views.py b/news/views.py new file mode 100644 index 0000000..e0b878a --- /dev/null +++ b/news/views.py @@ -0,0 +1,6 @@ +from django.http import HttpResponse +from news.models import Bunny + + +def index(request): + return HttpResponse('Number of Bunny(s): ' + str(Bunny.objects.all().count())) From 9fc3d840969a7381fb4d6cf284f4cd803635f1f9 Mon Sep 17 00:00:00 2001 From: Ashutosh Das Date: Fri, 26 Feb 2016 11:23:40 +0600 Subject: [PATCH 6/8] removed unused codes --- wsgi.py | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 wsgi.py diff --git a/wsgi.py b/wsgi.py deleted file mode 100644 index c1ffea2..0000000 --- a/wsgi.py +++ /dev/null @@ -1,4 +0,0 @@ -from hiren import app - -if __name__ == "__main__": - app.run() From dec67c3ece011d9dfe20329253b31afe46de4b1b Mon Sep 17 00:00:00 2001 From: Ashutosh Das Date: Fri, 26 Feb 2016 11:36:21 +0600 Subject: [PATCH 7/8] Added init --- etc/init/hiren_news.conf | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 etc/init/hiren_news.conf diff --git a/etc/init/hiren_news.conf b/etc/init/hiren_news.conf new file mode 100644 index 0000000..78e46a2 --- /dev/null +++ b/etc/init/hiren_news.conf @@ -0,0 +1,11 @@ +description "uWSGI server instance configured to serve Hiren-news" + +start on runlevel [2345] +stop on runlevel [!2345] + +setuid prism +setgid www-data + +env PATH=/home/prism/Hiren-news/.env/bin +chdir /home/prism/Hiren-news/ +exec uwsgi --ini hiren.ini \ No newline at end of file From e15b4a3076e8a2fbcde334cf355ec06e97ec87f6 Mon Sep 17 00:00:00 2001 From: Ashutosh Das Date: Fri, 26 Feb 2016 11:36:35 +0600 Subject: [PATCH 8/8] added uwsgi --- hiren.ini | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 hiren.ini diff --git a/hiren.ini b/hiren.ini new file mode 100644 index 0000000..8358213 --- /dev/null +++ b/hiren.ini @@ -0,0 +1,9 @@ +[uwsgi] +module=hiren.wsgi +master=True +process = 5 +pidfile=/tmp/news.pid +socket= /tmp/news.sock +vacuum=True +max-requests=5000 +daemonize=/home/prism/Hiren-news/hiren.log \ No newline at end of file