Browse Source

Adding Sphinx as a requirement, updating .hgignore

David Leonard 10 years ago
commit
67fa2558c7
100 changed files with 3359 additions and 0 deletions
  1. 12 0
      .hgignore
  2. 127 0
      README.md
  3. 22 0
      angular/bower.json
  4. 40 0
      angular/index.html
  5. 24 0
      angular/partials/githubTopContributions.partial.html
  6. 34 0
      angular/partials/githubUser.partial.html
  7. 24 0
      angular/partials/snippets.partial.html
  8. 34 0
      angular/scripts/app.js
  9. 13 0
      angular/scripts/controllers/appController.js
  10. 10 0
      angular/scripts/controllers/githubTopContributionsController.js
  11. 10 0
      angular/scripts/controllers/githubUserController.js
  12. 10 0
      angular/scripts/controllers/restAppController.js
  13. 12 0
      angular/scripts/factories/githubTopContributionsFactory.js
  14. 12 0
      angular/scripts/factories/githubUserFactory.js
  15. 12 0
      angular/scripts/factories/restAppFactory.js
  16. 20 0
      bower.json
  17. 0 0
      hackathon_starter/hackathon/__init__.py
  18. 7 0
      hackathon_starter/hackathon/admin.py
  19. 11 0
      hackathon_starter/hackathon/forms.py
  20. 0 0
      hackathon_starter/hackathon/migrations/__init__.py
  21. 25 0
      hackathon_starter/hackathon/models.py
  22. 0 0
      hackathon_starter/hackathon/scripts/__init__.py
  23. 162 0
      hackathon_starter/hackathon/scripts/github.py
  24. 60 0
      hackathon_starter/hackathon/scripts/instagram.py
  25. 24 0
      hackathon_starter/hackathon/scripts/linkedin.py
  26. 29 0
      hackathon_starter/hackathon/scripts/steam.py
  27. 147 0
      hackathon_starter/hackathon/scripts/tumblr.py
  28. 11 0
      hackathon_starter/hackathon/scripts/twilioapi.py
  29. 9 0
      hackathon_starter/hackathon/serializers.py
  30. 26 0
      hackathon_starter/hackathon/static/css/form.css
  31. BIN
      hackathon_starter/hackathon/static/img/github.png
  32. BIN
      hackathon_starter/hackathon/static/img/linkedin.jpg
  33. BIN
      hackathon_starter/hackathon/static/img/steam.png
  34. BIN
      hackathon_starter/hackathon/static/img/tumblr.png
  35. 17 0
      hackathon_starter/hackathon/templates/hackathon/api_examples.html
  36. 61 0
      hackathon_starter/hackathon/templates/hackathon/base.html
  37. 110 0
      hackathon_starter/hackathon/templates/hackathon/github.html
  38. 14 0
      hackathon_starter/hackathon/templates/hackathon/index.html
  39. 17 0
      hackathon_starter/hackathon/templates/hackathon/instagram.html
  40. 25 0
      hackathon_starter/hackathon/templates/hackathon/linkedin.html
  41. 47 0
      hackathon_starter/hackathon/templates/hackathon/login.html
  42. 40 0
      hackathon_starter/hackathon/templates/hackathon/navbar.html
  43. 42 0
      hackathon_starter/hackathon/templates/hackathon/register.html
  44. 31 0
      hackathon_starter/hackathon/templates/hackathon/steam.html
  45. 76 0
      hackathon_starter/hackathon/templates/hackathon/tumblr.html
  46. 12 0
      hackathon_starter/hackathon/templates/hackathon/twilio.html
  47. 3 0
      hackathon_starter/hackathon/tests.py
  48. 0 0
      hackathon_starter/hackathon/unittests/__init__.py
  49. 8 0
      hackathon_starter/hackathon/unittests/testcase.py
  50. 192 0
      hackathon_starter/hackathon/unittests/testgithub.py
  51. 925 0
      hackathon_starter/hackathon/unittests/teststeam.py
  52. 31 0
      hackathon_starter/hackathon/unittests/testtumblr.py
  53. 21 0
      hackathon_starter/hackathon/urls.py
  54. 256 0
      hackathon_starter/hackathon/views.py
  55. 0 0
      hackathon_starter/hackathon_starter/__init__.py
  56. 118 0
      hackathon_starter/hackathon_starter/settings.py
  57. 8 0
      hackathon_starter/hackathon_starter/urls.py
  58. 14 0
      hackathon_starter/hackathon_starter/wsgi.py
  59. 10 0
      hackathon_starter/manage.py
  60. 3 0
      ionic/.bowerrc
  61. 6 0
      ionic/.gitignore
  62. 26 0
      ionic/README.md
  63. 7 0
      ionic/bower.json
  64. 49 0
      ionic/config.xml
  65. 50 0
      ionic/gulpfile.js
  66. 83 0
      ionic/hooks/README.md
  67. 94 0
      ionic/hooks/after_prepare/010_add_platform_class.js
  68. 4 0
      ionic/ionic.project
  69. 21 0
      ionic/package.json
  70. 11 0
      ionic/plugins/ios.json
  71. BIN
      ionic/resources/android/icon/drawable-hdpi-icon.png
  72. BIN
      ionic/resources/android/icon/drawable-ldpi-icon.png
  73. BIN
      ionic/resources/android/icon/drawable-mdpi-icon.png
  74. BIN
      ionic/resources/android/icon/drawable-xhdpi-icon.png
  75. BIN
      ionic/resources/android/icon/drawable-xxhdpi-icon.png
  76. BIN
      ionic/resources/android/icon/drawable-xxxhdpi-icon.png
  77. BIN
      ionic/resources/android/splash/drawable-land-hdpi-screen.png
  78. BIN
      ionic/resources/android/splash/drawable-land-ldpi-screen.png
  79. BIN
      ionic/resources/android/splash/drawable-land-mdpi-screen.png
  80. BIN
      ionic/resources/android/splash/drawable-land-xhdpi-screen.png
  81. BIN
      ionic/resources/android/splash/drawable-land-xxhdpi-screen.png
  82. BIN
      ionic/resources/android/splash/drawable-land-xxxhdpi-screen.png
  83. BIN
      ionic/resources/android/splash/drawable-port-hdpi-screen.png
  84. BIN
      ionic/resources/android/splash/drawable-port-ldpi-screen.png
  85. BIN
      ionic/resources/android/splash/drawable-port-mdpi-screen.png
  86. BIN
      ionic/resources/android/splash/drawable-port-xhdpi-screen.png
  87. BIN
      ionic/resources/android/splash/drawable-port-xxhdpi-screen.png
  88. BIN
      ionic/resources/android/splash/drawable-port-xxxhdpi-screen.png
  89. BIN
      ionic/resources/icon.png
  90. BIN
      ionic/resources/ios/icon/icon-40.png
  91. BIN
      ionic/resources/ios/icon/icon-40@2x.png
  92. BIN
      ionic/resources/ios/icon/icon-50.png
  93. BIN
      ionic/resources/ios/icon/icon-50@2x.png
  94. BIN
      ionic/resources/ios/icon/icon-60.png
  95. BIN
      ionic/resources/ios/icon/icon-60@2x.png
  96. BIN
      ionic/resources/ios/icon/icon-60@3x.png
  97. BIN
      ionic/resources/ios/icon/icon-72.png
  98. BIN
      ionic/resources/ios/icon/icon-72@2x.png
  99. BIN
      ionic/resources/ios/icon/icon-76.png
  100. 0 0
      ionic/resources/ios/icon/icon-76@2x.png

+ 12 - 0
.hgignore

@@ -0,0 +1,12 @@
+syntax: glob
+
+.DS_Store
+db.sqlite3
+*.pyc
+bower_components/
+migrations/
+*.coverage
+Thumbs.db
+*/vendor
+ionic/platforms
+hackathon_starter/_build

+ 127 - 0
README.md

@@ -0,0 +1,127 @@
+Django Hackathon Starter
+------------------------
+
+## What is Django Hackathon Starter
+
+> Django Hackathon Starter aims to be a project which will aggegrate data from several APIs, producing a RESTful API which can be consumed by a client (also intended to be built). 
+
+Our deployment can be found [here](http://django-hackathon-starter.herokuapp.com/hackathon/).
+
+## Running this project
+
+In order to run this project, do the following:
+
+    # Install the requirements
+    pip install -r requirements.txt
+
+    # Perform database migrations
+    python manage.py migrate
+
+    # Run the server
+    python manage.py runserver
+
+## Front End dependencies
+
+This project relies on Bower for all front end libraries, to avoid pushing up large libraries such as `jQuery` and `Bootstrap`. To install `bower`, you will need to install `npm`, which now comes bundled with `node.js`. To install `npm`, simply install [node as follows](https://github.com/joyent/node/wiki/installing-node.js-via-package-manager). 
+
+First, install `bower`:
+
+    npm install -g bower
+
+Then:
+
+    # In the same directory as requirements.txt
+    bower install
+
+This will download and extract all the packages listed within `bower.json`. **Under no circumstance should any front-end libraries manually be pushed up to the repository.**
+
+Then:
+
+    # move bower_components into static folder
+    mv bower_components/ hackathon_starter/hackathon/static
+
+To install the front-end dependencies for the AngularJS client, do the following:
+
+    cd public
+    bower install
+    # Rename bower_components folder to vendor
+    mv bower_components/ vendor/
+
+
+## Testing
+
+This project aims to be as close to 100% tested as possible. For a good guide to testing using Python and `Mock`, `Nosetests` and `Unittests` libraries, please [read here](http://docs.python-guide.org/en/latest/writing/tests/).
+
+To run the tests:
+
+    hackthon-starter $ python manage.py test hackathon/unittests/
+
+## Code evaluation
+
+In order to write clean code with a consistent style guide, we'll be using `Pylint` to maintain our code. Pylint will display a ton of messages regarding things that should be fixed. 
+
+
+## RESTful endpoints
+
+Using the `Django REST framework, the current RESTful endpoints exist:
+
+    http://127.0.0.1:8000/hackathon/snippets/
+
+The list will appear empty at first, since the database model `Snippets` will be empty. To populate it with some sample data, run the following:
+
+    python manage.py shell
+    from hackathon.models import Snippet
+    from hackathon.serializers import SnippetSerializer
+    from rest_framework.renderers import JSONRenderer
+    from rest_framework.parsers import JSONParser
+
+    snippet = Snippet(code='foo = "bar"\n')
+    snippet.save()
+
+    snippet = Snippet(code='print "hello, world"\n')
+    snippet.save()
+
+The above will open the Django shell, and allow you to create objects and save them to the database. If you then navigate to the URL above, you will see the JSON output of the database model, `Snippet`. 
+
+## AngularJS Client
+
+As of `April 11th, 2015`, there is now a sample AngularJS client which pulls data from the Django sample API endpoint: `http://127.0.0.1:8000/hackathon/snippets/`. To test it, do the following:
+
+* Within the `public/` directory, run `python -m SimpleHTTPServer 80`. You may need `sudo` on your respective Operating System.
+* Navigate to: `http://localhost/#/snippets`. Here you will see whatever content was stored within the database model, `Snippet`. If nothing shows up, go back to the `RESTful endpoints` step to populate your database with some `Snippet` objects. 
+
+## Ionic Client
+
+As of `April 11th, 2015`, there is now a sample Ionic application which works on iOS. This application pulls data from the Django sample API endpoint: `http://127.0.0.1:8000/hackathon/snippets/`. In order to successfully run this project, you must do the following:
+
+    # Make sure django-hackathon-starter is running
+    python manage.py runserver
+
+    # Install cordova and ionic
+    # On a Mac, you'll need to use sudo
+    npm install -g cordova ionic 
+
+    cd ionic
+
+    # Add support for the iOS platform
+    ionic platform add ios
+
+    # Build the project
+    ionic build ios
+
+Running the final command, `ionic build ios` will generate an `.xcodeproj` file within `platforms/ionic`. You can open it and then run it, which you should then see a list of all the `Snippet` objects from the Django Hackathon Starter database. 
+
+You can also test the project in the browser by doing the following:
+
+    cd ionic
+    ionic serve 
+
+Running `ionic serve` will automatically open up your web browser and run the application.
+
+
+## Contributors
+
+* David Leonard
+* Eswari Swarna
+* Marco Quezada 
+* Wan Kim Mok

+ 22 - 0
angular/bower.json

@@ -0,0 +1,22 @@
+{
+  "name": "django-hackathon-starter",
+  "version": "0.0.0",
+  "authors": [
+    "David Leonard <sephirothcloud1025@yahoo.com>"
+  ],
+  "description": "Django boilerplate project for hackathons",
+  "keywords": [
+    "Django",
+    "Python",
+    "API",
+    "RESTful"
+  ],
+  "license": "MIT",
+  "dependencies": {
+    "bootstrap": "~3.3.4",
+    "jquery": "~2.1.3",
+    "bootstrap-social": "~4",
+    "angular": "~1.3.15",
+    "angular-ui-router": "~0.2.13"
+  }
+}

+ 40 - 0
angular/index.html

@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en-us" data-ng-app="restApp" data-ng-controller="appController">
+    <head>
+        <meta charset="utf-8">
+
+        <title data-ng-bind="pageTitle + ' | RestAPP'">RestAPP</title>
+
+        <!-- AngularJS -->
+        <script src="vendor/angular/angular.js"></script>
+        <script src="vendor/angular-ui-router/release/angular-ui-router.min.js"></script>
+
+        <!-- Bootstrap Core CSS -->
+        <link href="vendor/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
+
+        <!-- jQuery -->
+        <script src="vendor/jquery/dist/jquery.min.js"></script>
+
+        <!-- Bootstrap Core JavaScript -->
+        <script src="vendor/bootstrap/dist/js/bootstrap.min.js"></script>
+
+        <!-- Main application file -->
+        <script src="scripts/app.js"></script>
+
+        <!-- Controllers --> 
+        <script src="scripts/controllers/appController.js"></script>
+        <script src="scripts/controllers/restAppController.js"></script>
+        <script src="scripts/controllers/githubUserController.js"></script>
+        <script src="scripts/controllers/githubTopContributionsController.js"></script>
+
+        <!-- Factories -->
+        <script src="scripts/factories/restAppFactory.js"></script>
+        <script src="scripts/factories/githubUserFactory.js"></script>
+        <script src="scripts/factories/githubTopContributionsFactory.js"></script>
+
+    </head>
+
+    <body>
+        <div data-ui-view></div>
+    </body>
+</html>

+ 24 - 0
angular/partials/githubTopContributions.partial.html

@@ -0,0 +1,24 @@
+<div class="row text-center">
+	<h1> Github Top Contributed Repositories</h1>
+</div>
+
+<div class="col-lg-12">
+    <div class="table-responsive">
+        <table class="table table-bordered table-hover table-striped tablesorter">
+            <thead>
+                <tr>
+                    <th class="header">Repository Name</th>
+                    <th class="header">Total Commits</th>
+                    <th class="header">Author</th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr data-ng-repeat="data in githubTopContributions.data.committed">
+                        <td>{{ data.repo_name }}</td>
+                        <td>{{ data.total }}</td>
+                        <td>{{ data.author }}</td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</div>

+ 34 - 0
angular/partials/githubUser.partial.html

@@ -0,0 +1,34 @@
+<div class="row text-center"> <h1> Github User Data </h1>
+</div>
+
+<div class="col-lg-12">
+    <div class="table-responsive">
+        <table class="table table-bordered table-hover table-striped tablesorter">
+            <thead>
+                <tr>
+                    <th class="header">Public Repos</th>
+                    <th class="header">Public Gists</th>
+                    <th class="header">Name</th>
+                    <th class="header">Blog</th>
+                    <th class="header">Followers</th>
+                    <th class="header">Following</th>
+                    <th class="header">E-mail</th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr data-ng-repeat="data in githubUser.data.userData">
+                        <td>{{ data.public_repos }}</td>
+                        <td>{{ data.public_gists }}</td>
+                        <td>{{ data.name }}</td>
+                        <td>{{ data.blog }}</td>
+                        <td>{{ data.followers }}</td>
+                        <td>{{ data.following }}</td>
+                        <td>{{ data.email }}</td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
+
+
+

+ 24 - 0
angular/partials/snippets.partial.html

@@ -0,0 +1,24 @@
+<div class="row text-center">
+	<h1> Code Snippets </h1>
+</div>
+
+<div class="col-lg-12">
+    <div class="table-responsive">
+        <table class="table table-bordered table-hover table-striped tablesorter">
+            <thead>
+                <tr>
+                    <th class="header">Code</th>
+                    <th class="header">ID</th>
+                    <th class="header">Line Numbers</th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr data-ng-repeat="data in restData">
+	                    <td>{{ data.code }}</td>
+	                    <td>{{ data.id }}</td>
+	                    <td>{{ data.linenos }}</td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</div>

+ 34 - 0
angular/scripts/app.js

@@ -0,0 +1,34 @@
+'use strict';
+
+var restApp = angular.module('restApp', [
+    'ui.router'
+])
+.config(function($stateProvider, $urlRouterProvider) {
+    $stateProvider
+        .state('snippets', {
+            url: '/snippets',
+            templateUrl: 'partials/snippets.partial.html',
+            controller: 'restAppController',
+            data: {
+                pageTitle: 'Sample API Data'
+            }
+        })
+
+        .state('githubUser', {
+            url: '/githubUser',
+            templateUrl: 'partials/githubUser.partial.html',
+            controller: 'githubUserController',
+            data: {
+                pageTitle: 'Github User Data'
+            }
+        })
+
+        .state('githubTopContributions', {
+            url: '/githubTopContributions',
+            templateUrl: 'partials/githubTopContributions.partial.html',
+            controller: 'githubTopContributionsController',
+            data: {
+                pageTitle: 'Top Contributions on Github'
+            }
+        });
+});

+ 13 - 0
angular/scripts/controllers/appController.js

@@ -0,0 +1,13 @@
+'use strict';
+
+restApp.controller('appController', function($scope, $location) {
+    $scope.siteTitle = 'REST App';
+
+    $scope.$on('$stateChangeSuccess', function(event, toState) {
+        $scope.pageTitle = toState.data.pageTitle;
+    });
+
+    $scope.isActive = function(viewLocation) {
+        return viewLocation === $location.path();
+    };
+});

+ 10 - 0
angular/scripts/controllers/githubTopContributionsController.js

@@ -0,0 +1,10 @@
+'use strict';
+
+restApp.controller('githubTopContributionsController', function($scope, githubTopContributionsFactory) {
+    $scope.githubTopContributions = {};
+    
+    $scope.githubTopContributions = githubTopContributionsFactory.get().success(function(data) {
+    	$scope.githubTopContributions = data;
+    	console.log(data);
+    });
+});

+ 10 - 0
angular/scripts/controllers/githubUserController.js

@@ -0,0 +1,10 @@
+'use strict';
+
+restApp.controller('githubUserController', function($scope, githubUserFactory) {
+    $scope.githubUser = {};
+    
+    $scope.githubUser = githubUserFactory.get().success(function(data) {
+    	$scope.githubUser = data;
+    	console.log(data);
+    });
+});

+ 10 - 0
angular/scripts/controllers/restAppController.js

@@ -0,0 +1,10 @@
+'use strict';
+
+restApp.controller('restAppController', function($scope, restAppFactory) {
+    $scope.restData = {};
+    
+    $scope.restData = restAppFactory.get().success(function(data) {
+    	$scope.restData = data;
+    	console.log(data);
+    });
+});

+ 12 - 0
angular/scripts/factories/githubTopContributionsFactory.js

@@ -0,0 +1,12 @@
+'use strict';
+
+restApp.factory('githubTopContributionsFactory', function($http) {
+    return {
+        get: function() {
+            return $http({
+                url: 'http://127.0.0.1:8000/hackathon/githubTopRepositories/',
+                method: 'GET',
+            });
+        }
+    };
+});

+ 12 - 0
angular/scripts/factories/githubUserFactory.js

@@ -0,0 +1,12 @@
+'use strict';
+
+restApp.factory('githubUserFactory', function($http) {
+    return {
+        get: function() {
+            return $http({
+                url: 'http://127.0.0.1:8000/hackathon/githubUser/',
+                method: 'GET',
+            });
+        }
+    };
+});

+ 12 - 0
angular/scripts/factories/restAppFactory.js

@@ -0,0 +1,12 @@
+'use strict';
+
+restApp.factory('restAppFactory', function($http) {
+    return {
+        get: function() {
+            return $http({
+                url: 'http://127.0.0.1:8000/hackathon/snippets/',
+                method: 'GET',
+            });
+        }
+    };
+});

+ 20 - 0
bower.json

@@ -0,0 +1,20 @@
+{
+  "name": "django-hackathon-starter",
+  "version": "0.0.0",
+  "authors": [
+    "David Leonard <sephirothcloud1025@yahoo.com>"
+  ],
+  "description": "Django boilerplate project for hackathons",
+  "keywords": [
+    "Django",
+    "Python",
+    "API",
+    "RESTful"
+  ],
+  "license": "MIT",
+  "dependencies": {
+    "bootstrap": "~3.3.4",
+    "jquery": "~2.1.3",
+    "bootstrap-social": "~4"
+  }
+}

+ 0 - 0
hackathon_starter/hackathon/__init__.py


+ 7 - 0
hackathon_starter/hackathon/admin.py

@@ -0,0 +1,7 @@
+from django.contrib import admin
+from hackathon.models import UserProfile, Profile
+
+# Register your models here.
+admin.site.register(UserProfile)
+admin.site.register(Profile)
+

+ 11 - 0
hackathon_starter/hackathon/forms.py

@@ -0,0 +1,11 @@
+from django.contrib.auth.forms import UserCreationForm
+from django.contrib.auth.models import User
+from django import forms
+from hackathon.models import UserProfile
+
+class UserForm(forms.ModelForm):
+    password = forms.CharField(widget=forms.PasswordInput())
+
+    class Meta:
+        model = User
+        fields = ('username', 'email', 'password')

+ 0 - 0
hackathon_starter/hackathon/migrations/__init__.py


+ 25 - 0
hackathon_starter/hackathon/models.py

@@ -0,0 +1,25 @@
+from django.db import models
+from django.contrib.auth.models import User
+
+# Create your models here.
+class UserProfile(models.Model):
+    # This line is required. Links UserProfile to a User model instance.
+    user = models.OneToOneField(User)
+
+    # Override the __unicode__() method to return out something meaningful!
+    def __unicode__(self):
+        return self.user.username
+
+class Profile(models.Model):
+    user = models.ForeignKey(User)
+    oauth_token = models.CharField(max_length=200)
+    oauth_secret = models.CharField(max_length=200)
+
+class Snippet(models.Model):
+    created = models.DateTimeField(auto_now_add=True)
+    title = models.CharField(max_length=100, blank=True, default='')
+    code = models.TextField()
+    linenos = models.BooleanField(default=False)
+
+    class Meta:
+        ordering = ('created',)

+ 0 - 0
hackathon_starter/hackathon/scripts/__init__.py


+ 162 - 0
hackathon_starter/hackathon/scripts/github.py

@@ -0,0 +1,162 @@
+'''
+Module github.py contains a handful of methods
+for interacting with Github data.
+'''
+
+import requests
+import simplejson as json
+
+########################
+# GITHUB API CONSTANTS #
+########################
+
+API_BASE_URL = 'https://api.github.com/users/DrkSephy'
+
+def getUserData(clientID, clientSecret):
+	'''Get generic Github User data.'''
+	url = API_BASE_URL + '?' + clientID + '&' + clientSecret
+	req = requests.get(url)
+	jsonList = []
+	jsonList.append(json.loads(req.content))
+	parsedData = []
+	userData = {}
+	for data in jsonList: 
+		userData['name'] = data['name']
+		userData['blog'] = data['blog']
+		userData['email'] = data['email']
+		userData['public_gists'] = data['public_gists']
+		userData['public_repos'] = data['public_repos']
+		userData['avatar_url'] = data['avatar_url']
+		userData['followers'] = data['followers']
+		userData['following'] = data['following']
+	parsedData.append(userData)
+
+	return parsedData
+	
+
+def getUserRepositories(clientID, clientSecret):
+	'''Get a list of all repositories owned by a User.'''
+
+	pageNumber = 1
+
+
+	jsonList = []
+	repositories = []
+
+	while True:
+		req = requests.get('https://api.github.com/users/DrkSephy/repos?page=' + str(pageNumber) + '&' + clientID + '&' + clientSecret)
+		jsonList.append(json.loads(req.content))
+		if len(json.loads(req.content)) < 30:
+			break
+		elif len(json.loads(req.content)) >= 30:
+			pageNumber += 1
+
+	
+	for data in jsonList:
+		for datum in data:
+			repositories.append(datum['name'])
+			
+	return repositories
+
+def getForkedRepositories(clientID, clientSecret):
+	'''Get a list of all forked repositories by a user.'''
+	
+	pageNumber = 1
+
+	
+	jsonList = []
+
+	
+	forkedRepositories = []
+ 
+	while True:
+		req = requests.get('https://api.github.com/users/DrkSephy/repos?page=' + str(pageNumber) + '&' + clientID + '&' + clientSecret)
+		jsonList.append(json.loads(req.content))
+		if len(json.loads(req.content)) < 30:
+			break
+		elif len(json.loads(req.content)) >= 30:
+			pageNumber += 1
+
+
+	forkedRepos = {}
+	for data in jsonList:
+		for datum in data:
+			if datum['fork'] == True:
+				forkedRepos['name'] = datum['name']
+				forkedRepositories.append(forkedRepos)
+				forkedRepos = {}
+
+	return forkedRepositories
+
+def getTopContributedRepositories(repos, clientID, clientSecret):
+	'''Get a list of all commits for each repository owned.'''
+
+	jsonList = []
+	for repo in repos:
+		req = requests.get('https://api.github.com/repos/DrkSephy/' + repo + '/stats/contributors' + '?' + clientID + '&' + clientSecret)
+		jsonList.append(json.loads(req.content))
+
+	parsedData = []
+
+	indexNumber = -1
+	for item in jsonList:
+		indexNumber += 1
+		commits = {}
+		for data in item:
+			if data['author']['login'] == 'DrkSephy':
+				commits['author'] = data['author']['login']
+				commits['total'] = data['total']
+				commits['repo_name'] = repos[indexNumber]
+				parsedData.append(commits)
+
+	return parsedData
+
+def filterCommits(data):
+	'''Returns the top 10 committed repositories.'''
+
+	maxCommits = []
+	for i in range(1, 10):
+		maxCommitedRepo = max(data, key=lambda x:x['total'])
+		maxCommits.append(maxCommitedRepo)
+		index = data.index(maxCommitedRepo)
+		data.pop(index)
+	return maxCommits
+	
+	
+def getStarGazerCount(clientID, clientSecret):
+	'''Get Stargazer counts for all repositories.'''
+	
+	pageNumber = 1
+	jsonList = []
+	stargazers = []
+	while True:
+		req = requests.get('https://api.github.com/users/DrkSephy/repos?page=' + str(pageNumber) + '&' + clientID + '&' + clientSecret)
+		jsonList.append(json.loads(req.content))
+		if len(json.loads(req.content)) < 30:
+			break
+		elif len(json.loads(req.content)) >= 30:
+			pageNumber += 1
+
+
+	for data in jsonList:
+		for datum in data:
+			starData = {}
+			starData['stargazers_count'] = datum['stargazers_count']
+			starData['name'] = datum['name']
+			stargazers.append(starData)
+			
+	return stargazers
+
+def filterStarGazerCount(data):
+	'''Return top 10 starred repositories.'''
+	maxStars= []
+	for i in range(1, 10):
+		maxStarGazers = max(data, key=lambda x:x['stargazers_count'])
+		maxStars.append(maxStarGazers)
+		index = data.index(maxStarGazers)
+		data.pop(index)
+	return maxStars
+
+
+
+

+ 60 - 0
hackathon_starter/hackathon/scripts/instagram.py

@@ -0,0 +1,60 @@
+import requests
+import urllib
+import urllib2
+import json
+import simplejson as json2
+
+authorization_url = 'https://api.instagram.com/oauth/authorize/?client_id='
+access_token_url = 'https://api.instagram.com/oauth/access_token'
+
+class InstagramOauthClient(object):
+
+	access_token = None
+	user_data = None
+
+	def __init__(self, client_id, client_secret):
+		self.client_id 		= client_id
+		self.client_secret 	= client_secret
+
+	def get_authorize_url(self):
+		''' Obtains the authorization url. '''
+		auth_url = authorization_url + self.client_id +'&redirect_uri=http://localhost:8000/hackathon/instagram&response_type=code'
+		return auth_url
+
+	def get_access_token(self, code):
+		''' Obtains access token. '''
+
+		auth_setting = {'client_id': self.client_id,
+						'client_secret': self.client_secret,
+						'grant_type': 'authorization_code',
+						'redirect_uri': 'http://localhost:8000/hackathon/instagram',
+						'code': code
+						}
+
+		auth_setting_url =  urllib.urlencode(auth_setting)
+		req  = urllib2.Request(access_token_url, auth_setting_url)
+		content = urllib2.urlopen(req)
+		jsonlist = json.load(content)
+		self.access_token = jsonlist['access_token']
+		self.user_data = jsonlist['user']
+		print self.access_token
+
+
+	def get_tagged_media(self, tag):
+		''' Get recent tagged media. '''
+		tagged_media_url = 'https://api.instagram.com/v1/tags/'+tag+'/media/recent?access_token='+self.access_token# +'&count=2'
+		req = requests.get(tagged_media_url)
+		content = json2.loads(req.content)
+		data = content['data']
+
+		while len(data) <= 100:
+			next_url= content['pagination']['next_url']
+			req = requests.get(next_url)
+			content = json2.loads(req.content)
+			for i in content['data']:
+				data.append(i)
+		print len(data)
+		return data
+
+
+

+ 24 - 0
hackathon_starter/hackathon/scripts/linkedin.py

@@ -0,0 +1,24 @@
+import requests
+import simplejson as json
+
+
+consumer_key    = "7895bbnlh1k0mn"
+consumer_secret = "7CjUx1xTsF2WDRAI"
+oauth_token  	= "60b8f2c4-28b6-498d-a645-9dffb8baf47d"
+oauth_secret	= "3114e3d4-d725-482d-a11c-2e7607025a27"
+
+def getUserInfo():
+	req = requests.get("https://api.linkedin.com/v1/people/~")
+	jlist = []
+	jlist.append(json.loads(req.content))
+	parsedData = []
+	userData = {}
+	for data in jlist: 
+		userData['firstname'] = data['firstname']
+		userData['lasttname'] = data['lastname']
+		userData['email'] = data['email']
+		userData['connections'] = data['connections']
+		
+	parsedData.append(userData)
+
+	return parsedData

+ 29 - 0
hackathon_starter/hackathon/scripts/steam.py

@@ -0,0 +1,29 @@
+# pylint: disable=C0303
+
+import requests
+import json
+
+SteamUN = "Marorin"
+key = '231E98D442E52B87110816C3D5114A1D'
+
+def gamesPulling(steamID,key):
+    # Returns the JSON data from the Steam API based of one's 
+    # Steam ID number and returns a dictionary of gameids and minutes played.
+    steaminfo = {
+        'key': key, 
+        'steamid': steamID,
+        'format':'JSON',
+        'include_appinfo':'1'
+    }
+    r = requests.get('http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/', params=steaminfo)
+    d = json.loads(r.content)
+    return d['response']['games']
+ 
+def steamIDPulling(SteamUN,key):
+    #Pulls out and returns the steam id number for use in steam queries.
+    steaminfo = {'key': key,'vanityurl': SteamUN}
+    a = requests.get('http://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/', params=steaminfo)
+    k = json.loads(a.content)
+    SteamID = k['response']['steamid']
+    
+    return SteamID

+ 147 - 0
hackathon_starter/hackathon/scripts/tumblr.py

@@ -0,0 +1,147 @@
+import requests
+import simplejson as json
+import time 
+import urllib
+import re
+from bs4 import BeautifulSoup
+import urlparse
+import oauth2
+
+request_token_url   = 'http://www.tumblr.com/oauth/request_token'
+authorize_url       = 'http://www.tumblr.com/oauth/authorize'
+access_token_url    = 'http://www.tumblr.com/oauth/access_token'
+
+user_uri			= "http://api.tumblr.com/v2/user/info"
+blog_uri			= "http://api.tumblr.com/v2/blog/"
+
+class TumblrOauthClient(object):
+
+	token = None
+	oauth_verifier = None
+	oauth_token = None
+	oauth_token_secret = None
+	accessed = False
+
+
+
+	def __init__(self, consumer_key, consumer_secret):
+		self.consumer_key = consumer_key
+		self.consumer_secret = consumer_secret
+		self.consumer = oauth2.Consumer(consumer_key, consumer_secret)
+		
+
+
+	def authorize_url(self):
+		client = oauth2.Client(self.consumer)
+		resp, content = client.request(request_token_url, "GET")
+		#parse content
+		if not self.oauth_token:
+			request_token = dict(urlparse.parse_qsl(content))
+			self.oauth_token = request_token['oauth_token'] #'QBXdeeMKAnLzDbIG7dDNewTzRYyQoHZLbcn3bAFTCEFF5EXurl' #
+			self.oauth_token_secret = request_token['oauth_token_secret']#'u10SuRl2nzS8vFK4K7UPQexAvbIFBFrZBjA79XDlgoXFxv9ZhO' #
+		link = authorize_url+"?oauth_token="+self.oauth_token+"&redirect_uri=http%3A%2F%2Flocalhost%3A8000/hackathon/tumblr"
+		return link
+
+
+	def access_token_url(self, oauth_verifier=''):
+		self.accessed = True
+		token = oauth2.Token(self.oauth_token, self.oauth_token_secret)
+		self.oauth_verifier = oauth_verifier
+		print self.oauth_verifier
+		token.set_verifier(self.oauth_verifier)
+		client = oauth2.Client(self.consumer, token)
+		resp, content = client.request(access_token_url,"POST")
+		access_token = dict(urlparse.parse_qsl(content))
+		#set verified token
+		self.token = oauth2.Token(access_token['oauth_token'], access_token['oauth_token_secret'])
+		#print self.token
+			
+
+
+	def getUserInfo(self):
+		''' Returns users information. '''
+		client = oauth2.Client(self.consumer, self.token)
+		#print client
+		resp, content = client.request(user_uri, "POST")
+		if int(resp['status']) != 200:
+			raise Exception("Invalid response %s." % resp['status'])
+
+		#return content in json format
+		jsonlist = json.loads(content)
+		response = jsonlist['response']
+		user_info = response['user']
+		total_blogs = len(user_info['blogs'])
+		#print user_info
+		return user_info, total_blogs
+
+
+	def getBlogInfo(self, user):
+		''' Returns blogger's blog information '''
+		blog_info = blog_uri + user + ".tumblr.com/info?api_key="+self.consumer_key
+		req = requests.get(blog_info)
+		
+		#if int(req.status_code) != 200:
+		#	raise Exception("Invalid response %s." % resp['status'])
+		
+
+		jsonlist = json.loads(req.content)
+		response = jsonlist['response']
+		blog 	 = response['blog']
+		blog['updated'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(blog['updated']))
+		return blog
+
+
+	def getTaggedInfo(self, tag):
+		''' Return tags related to blog with certain tag. '''
+
+		tagged_uri = "http://api.tumblr.com/v2/tagged?tag="+tag+"&api_key="+self.consumer_key+"&limit=20"
+		req = requests.get(tagged_uri)
+		jsonlist = json.loads(req.content)
+
+		tags = []
+
+		meta = jsonlist['meta']
+		body = jsonlist['response']
+		for blog in body:
+			for data in blog:
+				if data == "tags":
+					#print blog[data]
+					for i in blog[data]:
+						m = re.match("(.*)(s*)s(t*)t(a*)a(r*)r(b*)b(u*)u(c*)c(k*)k(.*)", i.lower())
+						if not m:
+							tags.append(i)					
+
+		return tags	
+
+
+	def getTaggedBlog(self, tag):
+		''' Return the tagged blogs's captions or post.'''
+		
+		tagged_uri = "http://api.tumblr.com/v2/tagged?tag="+tag+"&api_key="+self.consumer_key+"&limit=20"
+		req = requests.get(tagged_uri)
+		jsonlist = json.loads(req.content)
+		
+		meta = jsonlist['meta']
+		body = jsonlist['response']
+
+		tagtext = []
+
+		for blog in body:
+			#print "####"
+			for data in blog:
+				#post
+				if data == "body":
+					if blog[data]:
+						#print blog[data]
+						soup = BeautifulSoup(blog[data])
+						text = soup.get_text()
+						tagtext.append(text)
+				#an image
+				if data == "caption":
+					if blog[data]:
+						#print blog[data]
+						soup = BeautifulSoup(blog[data])
+						text = soup.get_text()					
+						tagtext.append(text)
+		
+		return tagtext

+ 11 - 0
hackathon_starter/hackathon/scripts/twilioapi.py

@@ -0,0 +1,11 @@
+import twilio
+import requests
+from twilio.rest import TwilioRestClient
+ 
+account_sid = "AC7889a1889c1833bd7181e45e60372776"
+auth_token  = "1ad0315f3cc7a154aaaef048f1304f71"
+client = TwilioRestClient(account_sid, auth_token)
+ 
+def sendSMS(body, to, sender):
+	message = client.messages.create(body=body, to=to, from_=sender) 
+	return

+ 9 - 0
hackathon_starter/hackathon/serializers.py

@@ -0,0 +1,9 @@
+from django.forms import widgets
+from rest_framework import serializers
+from hackathon.models import Snippet
+
+
+class SnippetSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Snippet
+        fields = ('id', 'title', 'code', 'linenos')

+ 26 - 0
hackathon_starter/hackathon/static/css/form.css

@@ -0,0 +1,26 @@
+
+div.well{
+  height: 250px;
+} 
+
+.Absolute-Center {
+  margin: auto;
+  position: absolute;
+  top: 0; left: 0; bottom: 0; right: 0;
+}
+
+.Absolute-Center.is-Responsive {
+  width: 50%; 
+  height: 50%;
+  min-width: 200px;
+  max-width: 400px;
+  padding: 40px;
+}
+
+#logo-container{
+  margin: auto;
+  margin-bottom: 10px;
+  width:200px;
+  height:30px;
+  background-image:url('http://placehold.it/200x30/000000/ffffff/&text=Django+Hackathon+Starter');
+}

BIN
hackathon_starter/hackathon/static/img/github.png


BIN
hackathon_starter/hackathon/static/img/linkedin.jpg


BIN
hackathon_starter/hackathon/static/img/steam.png


BIN
hackathon_starter/hackathon/static/img/tumblr.png


+ 17 - 0
hackathon_starter/hackathon/templates/hackathon/api_examples.html

@@ -0,0 +1,17 @@
+<html>
+{% include 'hackathon/base.html' %}
+<body>
+
+
+	<div class="row text-center">
+	    <div class="col-sm-4"><a href="http://127.0.0.1:8000/hackathon/githubResume/">Github Example</a></div>
+	    <div class="col-sm-4"><a href="http://127.0.0.1:8000/hackathon/steam/">Steam Example</a></div>
+	    <div class="col-sm-4"><a href={{tumblr_url}}>Tumblr Example</a></div>
+		<div class="col-sm-4"><a href="http://127.0.0.1:8000/hackathon/linkedin/">LinkedIn Example</a></div>
+		<div class="col-sm-4"><a href="http://127.0.0.1:8000/hackathon/twilio/">Twilio Example</a></div>
+		<div class="col-sm-4"><a href="{{instagram_url}}">Instagram Example</a></div>
+
+  	</div>
+
+</body>
+</html>

+ 61 - 0
hackathon_starter/hackathon/templates/hackathon/base.html

@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title> Django Hackathon Starter </title>
+    <script src="/static/bower_components/jquery/dist/jquery.js"></script>
+    <script type="text/javascript" src="/static/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
+    
+    
+    <link rel="stylesheet" href="/static/bower_components/bootstrap/dist/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/static/bower_components/bootstrap/dist/css/bootstrap-theme.min.css">
+    <link rel="stylesheet" href="/static/bower_components/bootstrap-social/bootstrap-social.css">
+    <link rel="stylesheet" href="/static/bower_components/font-awesome/css/font-awesome.min.css">
+
+  </head>
+    
+  <body>
+    <nav class="navbar navbar-default" role="navigation">
+      <div class="container-fluid">
+        <!-- Brand and toggle get grouped for better mobile display -->
+        <div class="navbar-header">
+          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+            <span class="sr-only">Toggle navigation</span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="navbar-brand" href="/hackathon">Django Hackathon Starter</a>
+      </div>
+
+      <!-- Collect the nav links, forms, and other content for toggling -->
+      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+        <ul class="nav navbar-nav navbar-left">
+          {% if user.is_authenticated %}
+          <li><a href="/hackathon/api">API</a></li>
+          {% endif %}
+        </ul>
+        <ul class="nav navbar-nav navbar-right">
+          {% if not user.is_authenticated %}
+            <li class="active"><a href="/hackathon/register">Register <span class="sr-only">(current)</span></a></li>
+            
+            <li><a href="/hackathon/login">Login</a></li>
+          {% endif %}
+            
+        </ul>
+        
+        <ul  class="nav navbar-nav navbar-right">
+          {% if user.is_authenticated %}
+    
+            <li><a>Hello {{user}}</a></li>
+            <li><a href="/hackathon/logout/">Logout</a></li>
+          {% endif %}
+        </ul>
+          
+          
+          </li>
+         </ul>
+        </div><!-- /.navbar-collapse -->
+      </div><!-- /.container-fluid -->
+    </nav>
+  </body>
+</html>

+ 110 - 0
hackathon_starter/hackathon/templates/hackathon/github.html

@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+
+    <h1 class="text-center"> Github Resume </h1>
+	<div class="col-lg-12">
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover table-striped tablesorter">
+                <thead>
+                <tr>
+                <th class="header"> Username <i class="icon-sort"></i></th>
+                <th class="header"> Blog <i class="icon-sort"></i></th>
+                <th class="header"> Public Repos <i class="icon-sort"></i></th>
+                <th class="header"> Public Gists <i class="icon-sort"></i></th>
+                <th class="header"> Email <i class="icon-sort"></i></th>
+                <th class="header"> Followers <i class="icon-sort"></i></th>
+                <th class="header"> Following <i class="icon-sort"></i></th>
+                </tr>
+            </thead>
+            <tbody>
+
+            {% for key in data.userData %}
+                <tr>
+                    <td>{{ key.name }}</td>
+                    <td>{{ key.blog }}</td>
+                    <td>{{ key.public_repos }}</td>
+                    <td>{{ key.public_gists }}</td>
+                    <td>{{ key.email }}</td>
+                    <td>{{ key.followers }}</td>
+                    <td>{{ key.following }}</td>
+    			</tr>
+            {% endfor %}
+
+            </tbody>
+            </table>
+        </div>
+    </div>
+
+    <div class="col-xs-4">
+        <h2> Top Contributed Repositories </h2>
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover table-striped tablesorter">
+                <thead>
+                <tr>
+                <th class="header"> Repository <i class="icon-sort"></i></th>
+                <th class="header"> Total <i class="icon-sort"></i></th>
+                </tr>
+            </thead>
+            <tbody>
+
+            {% for key in data.filteredData %}
+                <tr>
+                    <td>{{ key.repo_name }}</td>
+                    <td>{{ key.total }}</td>
+                </tr>
+            {% endfor %}
+
+            </tbody>
+            </table>
+        </div>
+    </div>
+    <div class="col-xs-4">
+        <h2> Top Starred Repositories </h2>
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover table-striped tablesorter">
+                <thead>
+                <tr>
+                <th class="header"> Repository <i class="icon-sort"></i></th>
+                <th class="header"> Count <i class="icon-sort"></i></th>
+                </tr>
+            </thead>
+            <tbody>
+
+            {% for key in data.filteredStargazers %}
+                <tr>
+                    <td>{{ key.name }}</td>
+                    <td>{{ key.stargazers_count }}</td>
+                </tr>
+            {% endfor %}
+
+            </tbody>
+            </table>
+        </div>
+    </div>
+
+    <div class="col-xs-4">
+        <h2> Contributions </h2>
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover table-striped tablesorter">
+                <thead>
+                <tr>
+                <th class="header"> Repository <i class="icon-sort"></i></th>
+                </tr>
+            </thead>
+            <tbody>
+
+            {% for key in data.forkedRepos %}
+                <tr>
+                    <td>{{ key.name }}</td>
+                </tr>
+            {% endfor %}
+
+            </tbody>
+            </table>
+        </div>
+    </div>
+
+</body>
+</html>

+ 14 - 0
hackathon_starter/hackathon/templates/hackathon/index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+
+<html>
+    {% include 'hackathon/base.html' %}
+
+    <body>
+    	{% if user.is_authenticated %}
+        	<h1>Api Example</h1>
+        	<strong>{{ boldmessage }}</strong><br />
+        {% else %}
+        	<h1> Please register/login! </h1>
+        {% endif %}
+    </body>
+</html>

+ 17 - 0
hackathon_starter/hackathon/templates/hackathon/instagram.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+	<h1 class="text-center"> {{ title }}</h1> 
+	<br>
+	<div class="col-lg-12">
+		<div class="table-responsive">
+			<h2> #{{search_tag}} </h2>
+			<table class="table">
+				{% for i in tagged_media %}
+					<img src="{{i.images.thumbnail.url}}">
+				{% endfor %}		
+			</table>
+		</div>
+	</div>	
+</html>

+ 25 - 0
hackathon_starter/hackathon/templates/hackathon/linkedin.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+	<h1>user information</h1>
+	<table>
+	<tr>
+	<th>First name</th>
+	<th>lastname</th>
+	<th>email</th>
+	<th>connection</th>
+	</tr>
+	{% for key in userinfo %}
+    <tr>
+    <td>{{ key.firstname }}</td>
+    <td>{{ key.lastname}}</td>
+    <td>{{ key.email }}</td>
+    <td>{{ key.connectionss }}</td>
+    </tr>
+    {% endfor %}
+
+     </table>
+</body>
+</html>
+

+ 47 - 0
hackathon_starter/hackathon/templates/hackathon/login.html

@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+    {% include 'hackathon/base.html' %}
+    <style>
+      .form-signin {
+        max-width: 550px;
+        padding: 15px;
+        margin: 0 auto;
+      }    
+    </style>
+
+    <body>
+      <div class="container text-center">
+        <form class="form-signin" id="login_form" method="post" action="/hackathon/login/">
+          {% csrf_token %}
+          {% load bootstrap %}
+          <h2 class="form-signin-heading">Login</h2>
+          <br>
+          <input type="text" name="username" class="form-control" placeholder="Username" value="" required autofocus>
+          <br>
+          <input type="password" name="password" class="form-control" placeholder="Password" value=""required>
+          <br>
+          <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
+          <input type="hidden" name="submit" value="submit" />
+        </form>
+      </div>
+
+      <div class="form-signin">
+        <a class="btn btn-block btn-social btn-facebook">
+          <i class="fa fa-facebook"></i>
+          Sign in with Facebook
+        </a>          
+        <a class="btn btn-block btn-social btn-twitter" href="http://127.0.0.1:8000/hackathon/twitter_login/">
+          <i class="fa fa-twitter"></i>
+          Sign in with Twitter
+        </a>
+        <a class="btn btn-block btn-social btn-instagram" href="http://localhost:8000/hackathon/instagram_login/">
+          <i class="fa fa-instagram"></i>
+          Sign in with Instagram
+        </a>
+        <a class="btn btn-block btn-social btn-google-plus">
+          <i class="fa fa-google-plus"></i>
+          Sign in with Google
+        </a>          
+      </div>
+    </body>
+</html>

+ 40 - 0
hackathon_starter/hackathon/templates/hackathon/navbar.html

@@ -0,0 +1,40 @@
+<body>
+  <nav class="navbar navbar-default" role="navigation">
+      <div class="container-fluid">
+        <!-- Brand and toggle get grouped for better mobile display -->
+        <div class="navbar-header">
+          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+            <span class="sr-only">Toggle navigation</span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="navbar-brand" href="#">Django Hackathon Starter</a>
+      </div>
+
+      <!-- Collect the nav links, forms, and other content for toggling -->
+      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+        <ul class="nav navbar-nav navbar-right">
+          {% if not user.is_authenticated %}
+            <li class="active"><a href="/hackathon/register">Register <span class="sr-only">(current)</span></a></li>
+            
+            <li><a href="/hackathon/login">Login</a></li>
+          {% endif %}
+            
+        </ul>
+        
+        <ul  class="nav navbar-nav navbar-right">
+          {% if user.is_authenticated %}
+    
+            <li><a>Hello {{user}}</a></li>
+            <li><a href="/hackathon/logout/">Logout</a></li>
+          {% endif %}
+        </ul>
+          
+          
+          </li>
+        </ul>
+      </div><!-- /.navbar-collapse -->
+    </div><!-- /.container-fluid -->
+  </nav>
+</body>

+ 42 - 0
hackathon_starter/hackathon/templates/hackathon/register.html

@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+    {% include 'hackathon/base.html' %}
+    <link rel="stylesheet" href="/static/css/form.css">
+    <body>
+        {% if registered %}
+          <strong>Thank you for registering!</strong>
+          <a href="/hackathon/">Return to the homepage.</a><br />
+        
+        {% else %}
+          <div class='container text-center'>
+              <h2 class="form-signin-heading">Sign Up</h2>
+              <br>
+              <form class="form-horizontal" id="user_form" method="post" action="/hackathon/register/"
+                enctype="multipart/form-data">
+                {% csrf_token %}
+                {% load bootstrap %} 
+
+                <table>
+                  <tr>
+                     
+                      <td class="container text-center">{{ user_form.username | bootstrap_horizontal}}</td>
+                  </tr>
+
+                  <tr>
+                     
+                      <td class="container text-center">{{ user_form.email | bootstrap_horizontal}}</td>
+                  </tr>
+
+                  <tr>
+                     
+                      <td class="container text-center">{{ user_form.password | bootstrap_horizontal}}</td>
+                  </tr>
+                </table>
+                <button class="btn btn-lg btn-primary" type="submit">Register</button>
+                <input type="hidden" name="submit" value="Register" />
+              </form>
+            </div>
+          {% endif %}
+    </body>
+</html>
+

+ 31 - 0
hackathon_starter/hackathon/templates/hackathon/steam.html

@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+
+	<h1 class="text-center"> Steam API </h1>
+		<div class="col-lg-12">
+	        <div class="table-responsive">
+	            <table class="table table-bordered table-hover table-striped tablesorter">
+	                <thead>
+	                <tr>
+	                <th class="header"> Game ID <i class="icon-sort"></i></th>
+	                <th class="header"> Game Name <i class="icon-sort"></i></th>
+	                <th class="header"> Minutes Played <i class="icon-sort"></i></th>
+	            </thead>
+	            <tbody>
+
+	            {% for game in game %}
+	                <tr>
+	                    <td>{{ game.appid }}</td>
+	                    <td>{{ game.name }}</td>
+	                    <td>{{ game.playtime_forever }}</td>
+	    			</tr>
+	            {% endfor %}
+
+	            </tbody>
+	            </table>
+	        </div>
+	    </div>
+</body>
+</html>

+ 76 - 0
hackathon_starter/hackathon/templates/hackathon/tumblr.html

@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+	<h1 class="text-center"> {{ title }}</h1> 
+	<br>	
+	<div class="col-lg-12">
+		<div class="table-responsive">
+			<h2> BLOGGER </h2>
+			<table class="table table-bordered">
+				<tr>
+					<th>Name</th>
+					<td>{{blogData.name}}</td>
+				</tr>
+				<tr>
+					<th>Posts</th>
+					<td>{{blogData.posts}}</td>				
+				</tr>
+				<tr>
+					<th>Blog title</th>
+					<td>{{blogData.title}}</td>				
+				</tr>
+				<tr>
+					<th>Last updated</th>
+					<td>{{blogData.updated}}</td>				
+				</tr>
+				<tr>
+					<th>Description</th>
+					<td>{{blogData.description}}</td>				
+				</tr>				
+			</table>
+		</div>
+	</div>
+
+	<div class="col-md-4">
+		<div class="table-responsive">
+			<h2> #starbucks </h2>
+			<table class="table table-bordered">
+				{% for i in blogTag %}
+				<tr>
+					<td> {{i}} </td>
+				</tr>
+				{% endfor %}		
+			</table>
+		</div>
+	</div>
+
+	<div class="col-md-4">
+		<div class="table-responsive">
+			<h2> Comments </h2>
+			<table class="table table-bordered">
+				{% for i in blogontag %}
+				<tr>
+					<td> {{i}} </td>
+				</tr>
+				{% endfor %}		
+			</table>
+		</div>
+	</div>
+	<div class="col-md-4">
+		<div class="table-responsive">
+			<h2> User's Info </h2>
+			<table class="table table-bordered">
+				<tr>
+					<th>Name</th>
+					<td>{{userinfo.name}}</td>
+				</tr>	
+				<tr>
+					<th>Total Blogs</th>
+					<td>{{total_blog}}</td>
+				</tr>
+			</table>
+		</div>
+	</div>
+
+</html>

+ 12 - 0
hackathon_starter/hackathon/templates/hackathon/twilio.html

@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+
+    <h1 class="text-center"> Twilio Messages </h1>
+    {{ context }}
+    </div>
+    
+
+</body>
+</html>

+ 3 - 0
hackathon_starter/hackathon/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 0 - 0
hackathon_starter/hackathon/unittests/__init__.py


+ 8 - 0
hackathon_starter/hackathon/unittests/testcase.py

@@ -0,0 +1,8 @@
+import unittest
+
+def fun(x):
+    return x + 1
+
+class MyTest(unittest.TestCase):
+    def test(self):
+        self.assertEqual(fun(3), 4)

File diff suppressed because it is too large
+ 192 - 0
hackathon_starter/hackathon/unittests/testgithub.py


+ 925 - 0
hackathon_starter/hackathon/unittests/teststeam.py

@@ -0,0 +1,925 @@
+import unittest
+from mock import Mock, patch, MagicMock
+from django.conf import settings
+from hackathon.scripts.steam import *
+
+
+class SteamTests(unittest.TestCase):
+
+    def setup(self):
+        self.API_URL = 'http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/'
+        self.APIKEY = '231E98D442E52B87110816C3D5114A1D'
+        self.userID = 'Marorin'
+        self.steamnum = '76561197997115778'
+
+    def testGetUserIDNum(self):
+        '''Test for steam.py method'''
+        
+        # Pulling from setUp
+        userID = self.userID
+        API_URL = self.API_URL
+        APIKEY = self.APIKEY   
+ 
+        # constructing the URL
+        self.url = API_URL + '?' + APIKEY + '&' + userID
+
+        with patch('hackathon.scripts.steam.steamIDpulling') as mock_steamIDPulling:
+            # Mocking the return value of this method.
+            mock_steamIDpulling = 76561197997115778
+            self.assertEqual(steamIDPulling(userID,APIKEY),mock_steamIDpulling)
+
+    def testgamespulling(self):
+        '''Test gamesPulling method'''
+        with patch('hackathon.scripts.steam.gamesPulling) as mock_gamesPulling:
+            jsonList = [{
+				"appid": 4000,
+				"name": "Garry's Mod",
+				"playtime_forever": 0,
+				"img_icon_url": "d9101cbeddcc4ff06c7fa1936c3f381b0bbf2e92",
+				"img_logo_url": "dca12980667e32ab072d79f5dbe91884056a03a2",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 6550,
+				"name": "Devil May Cry 3: Special Edition",
+				"playtime_forever": 217,
+				"img_icon_url": "5c216acd743413bee9ae18c0d5302e5939ca689f",
+				"img_logo_url": "b26ae9eee26c206b2b3bfab7d365f707e20854a3"
+			},
+			{
+				"appid": 10500,
+				"name": "Empire: Total War",
+				"playtime_forever": 0,
+				"img_icon_url": "dc10f7bad53d3d922c196d116b1c5d6a4b274768",
+				"img_logo_url": "d60c77df97439e8434f0d0be9c3e2d9f39699991",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 17460,
+				"name": "Mass Effect",
+				"playtime_forever": 1242,
+				"img_icon_url": "57be81f70afa48c65437df93d75ba167a29687bc",
+				"img_logo_url": "7501ea5009533fa5c017ec1f4b94725d67ad4936"
+			},
+			{
+				"appid": 12810,
+				"name": "Overlord II",
+				"playtime_forever": 0,
+				"img_icon_url": "cc38122745bd44454e7e122e86023fb35e652d9d",
+				"img_logo_url": "7107ed1429c4be7637571fdf262f61af6bc7d4a2"
+			},
+			{
+				"appid": 45700,
+				"name": "Devil May Cry 4",
+				"playtime_forever": 925,
+				"img_icon_url": "1f869ad15ffdc1eb406c5d1635c9c0efb2e91f12",
+				"img_logo_url": "5b274e94aec7806da9a1b5ba5334668781ff0fd2"
+			},
+			{
+				"appid": 24980,
+				"name": "Mass Effect 2",
+				"playtime_forever": 4040,
+				"img_icon_url": "e6f3b9b0762fd4d42a732abfc41887f6c5903a52",
+				"img_logo_url": "d446fe6d77c9f434cd7fd871400b978fc01fb4e7"
+			},
+			{
+				"appid": 4540,
+				"name": "Titan Quest",
+				"playtime_forever": 0,
+				"img_icon_url": "d59f857aed0d38c69960a9d80e3d23e0863f4e01",
+				"img_logo_url": "e82186f6efe8d5d593c2fb1b57f8b1e056e6d82e",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 21100,
+				"name": "F.E.A.R. 3",
+				"playtime_forever": 0,
+				"img_icon_url": "01b73115a3ff7315d14f0bcf7beff01ef76162b4",
+				"img_logo_url": "d2fcf83ec76e845ed19f4ff8324304e2981af391",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 620,
+				"name": "Portal 2",
+				"playtime_forever": 29,
+				"img_icon_url": "2e478fc6874d06ae5baf0d147f6f21203291aa02",
+				"img_logo_url": "d2a1119ddc202fab81d9b87048f495cbd6377502",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 45760,
+				"name": "Ultra Street Fighter IV",
+				"playtime_forever": 111,
+				"img_icon_url": "473fcea2eb516528608dff7f9e3e61009d76a282",
+				"img_logo_url": "bdd481249e579f852056b51db32a6279444d4f47",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 21090,
+				"name": "F.E.A.R.",
+				"playtime_forever": 0,
+				"img_icon_url": "71f118282be5aaa34eb82506593130ecfcc6a90b",
+				"img_logo_url": "df122e0ee9eb2a5371910ffda0f8a3382e09232e"
+			},
+			{
+				"appid": 21110,
+				"name": "F.E.A.R.: Extraction Point",
+				"playtime_forever": 0,
+				"img_icon_url": "153d4f89ef0bd59a0039c396ff963a31d4d5e71b",
+				"img_logo_url": "df122e0ee9eb2a5371910ffda0f8a3382e09232e"
+			},
+			{
+				"appid": 21120,
+				"name": "F.E.A.R.: Perseus Mandate",
+				"playtime_forever": 0,
+				"img_icon_url": "7b1d0271f2735ca66e1cb681eb4da1a7c985d53f",
+				"img_logo_url": "df122e0ee9eb2a5371910ffda0f8a3382e09232e"
+			},
+			{
+				"appid": 16450,
+				"name": "F.E.A.R. 2: Project Origin",
+				"playtime_forever": 0,
+				"img_icon_url": "6611d8b01c7a2cc3538c478c044d1e09f3140eaa",
+				"img_logo_url": "41734347c3f05fe7dd797570130f5069c08f9d1b"
+			},
+			{
+				"appid": 32800,
+				"name": "The Lord of the Rings: War in the North",
+				"playtime_forever": 0,
+				"img_icon_url": "56dcf3fe99a90c25daae1cbe84319bb8af3c6ac5",
+				"img_logo_url": "b90d899806ebaff87ed7d2cdc4d9e0a3f11b73b0",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 107100,
+				"name": "Bastion",
+				"playtime_forever": 45,
+				"img_icon_url": "8377b4460f19465c261673f76f2656bdb3288273",
+				"img_logo_url": "d113d66ef88069d7d35a74cfaf2e2ee917f61133",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 55230,
+				"name": "Saints Row: The Third",
+				"playtime_forever": 246,
+				"img_icon_url": "ec83645f13643999e7c91da75d418053d6b56529",
+				"img_logo_url": "1129528455a8b297fb6404cbb90e802a62881b11",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 34270,
+				"name": "SEGA Genesis & Mega Drive Classics",
+				"playtime_forever": 4,
+				"img_icon_url": "48a187fa87c58b798646a430d446dd36eeabd1a4",
+				"img_logo_url": "212f55b3ea1a8c70427890896e93a37b49f57187",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71340,
+				"name": "Sonic Generations",
+				"playtime_forever": 520,
+				"img_icon_url": "efda039147f0968bc726c547ff3809f98b69964a",
+				"img_logo_url": "21ec1e24c31a50500bbddb8c8c8add451e6dcbe1",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 72850,
+				"name": "The Elder Scrolls V: Skyrim",
+				"playtime_forever": 2431,
+				"img_icon_url": "b9aca8a189abd8d6aaf09047dbb0f57582683e1c",
+				"img_logo_url": "c5af3cde13610fca25cd17634a96d72487d21e74",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 41070,
+				"name": "Serious Sam 3: BFE",
+				"playtime_forever": 0,
+				"img_icon_url": "2e7a17d4b345ffb13ef3d9e39257c2659fe4a86b",
+				"img_logo_url": "cc3a3c30187b5fbbd0a8861ad08b4f7d779ba239",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 57400,
+				"name": "Batman: Arkham City™",
+				"playtime_forever": 1271,
+				"img_icon_url": "4c208d1365ea5614326717ecfcfea1196ef48e70",
+				"img_logo_url": "5456a41d4076244a6c593cbb260c3384493a7727",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 200260,
+				"name": "Batman: Arkham City GOTY",
+				"playtime_forever": 592,
+				"img_icon_url": "746ecf3ce44b2525eb7ad643e76a3b60913d2662",
+				"img_logo_url": "9b229e12fd5ce27bd101d5862c19b1a6e3d01239",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 108710,
+				"name": "Alan Wake",
+				"playtime_forever": 0,
+				"img_icon_url": "ec7953511aaaf5a2c2093b872b5b43c6cab56462",
+				"img_logo_url": "0f9b6613ac50bf42639ed6a2e16e9b78e846ef0a",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 207490,
+				"name": "Rayman Origins",
+				"playtime_forever": 585,
+				"img_icon_url": "1e155c2bc13e8793aed8bb61fdac798fe0d49de7",
+				"img_logo_url": "ebfd3f8da2b0416d71724a2929740a72a6eaabf4"
+			},
+			{
+				"appid": 41500,
+				"name": "Torchlight",
+				"playtime_forever": 130,
+				"img_icon_url": "b2a2a43e401dce3c69898b67b1b8af4481d96b08",
+				"img_logo_url": "e36226c6a0575e6e1838e1f915e91f8b31ab3008",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 200710,
+				"name": "Torchlight II",
+				"playtime_forever": 1011,
+				"img_icon_url": "40776762bb63c4eded37d1a2b4431a90aa57ea84",
+				"img_logo_url": "fd37abb86628ff54ed304f75c2fb7cf75a4f6902",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 205350,
+				"name": "Mortal Kombat Kollection",
+				"playtime_forever": 0,
+				"img_icon_url": "048e463386c8f0049d6e08bbf8f5ebb5d232394f",
+				"img_logo_url": "44281a64a93a583fdd2435036ac794e7dcc7beb8",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 202750,
+				"name": "Alan Wake's American Nightmare",
+				"playtime_forever": 0,
+				"img_icon_url": "313aabf37ed0b521ad969d3fe21768d31300f1ca",
+				"img_logo_url": "d3593fa14e4ea8685dc6b1f71dbaa980c013ff02",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 113200,
+				"name": "The Binding of Isaac",
+				"playtime_forever": 503,
+				"img_icon_url": "383cf045ca20625db18f68ef5e95169012118b9e",
+				"img_logo_url": "d9a7ee7e07dffed1700cb8b3b9482105b88cc5b5",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 35140,
+				"name": "Batman: Arkham Asylum GOTY Edition",
+				"playtime_forever": 0,
+				"img_icon_url": "e52f91ecb0d3f20263e96fe188de1bcc8c91643e",
+				"img_logo_url": "172e0928b845c18491f1a8fee0dafe7a146ac129",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 211420,
+				"name": "Dark Souls: Prepare to Die Edition",
+				"playtime_forever": 5309,
+				"img_icon_url": "a24804c6c8412c8cd9d50efd06bf03fa58ff80a9",
+				"img_logo_url": "d293c8e38f56de2c7097b2c7a975caca49029a8b",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 204300,
+				"name": "Awesomenauts",
+				"playtime_forever": 9,
+				"img_icon_url": "4996933171d0804bd0ceb7b9a0e224b3139d18ba",
+				"img_logo_url": "a2eba6157703c60bfcc199f06df5f1568c9835bb",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 204630,
+				"name": "Retro City Rampage™ DX",
+				"playtime_forever": 0,
+				"img_icon_url": "423b87d4a5a00ff6e807558e565b0b515fadf61b",
+				"img_logo_url": "3ca51d2767c5de3358c4f1824f1b362a9494983f",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 214560,
+				"name": "Mark of the Ninja",
+				"playtime_forever": 1,
+				"img_icon_url": "220f33169c93c2f6381cd785399fb52bfc79309f",
+				"img_logo_url": "c20501309696e5bcda98e9e4f2649abc5720a1d1",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 49520,
+				"name": "Borderlands 2",
+				"playtime_2weeks": 24,
+				"playtime_forever": 7526,
+				"img_icon_url": "a3f4945226e69b6196074df4c776e342d3e5a3be",
+				"img_logo_url": "86b0fa5ddb41b4dfff7df194a017f3418130d668",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 205950,
+				"name": "Jet Set Radio",
+				"playtime_forever": 644,
+				"img_icon_url": "884cfa9f5f615e297f8c53a2010f1b63835e44b5",
+				"img_logo_url": "3272dfd2e30df5629bfbaa851ea503e9ee28b75a",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 213610,
+				"name": "Sonic Adventure™ 2 ",
+				"playtime_forever": 0,
+				"img_icon_url": "0ff2b133493b0bf7f1c16a38a83e7053f0b90f2d",
+				"img_logo_url": "b59ee5bd744212a79db6fd8f71aec6729671da2b",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 205790,
+				"name": "Dota 2 Test",
+				"playtime_forever": 20,
+				"img_icon_url": "",
+				"img_logo_url": ""
+			},
+			{
+				"appid": 218680,
+				"name": "Scribblenauts Unlimited",
+				"playtime_forever": 0,
+				"img_icon_url": "e933a9993b7d0b905dbb37636a97339a2c277e0f",
+				"img_logo_url": "c3f8420cd87dd772df8a35013e3538e964ecc2b8",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 223220,
+				"name": "Giana Sisters: Twisted Dreams",
+				"playtime_forever": 115,
+				"img_icon_url": "ac543243f2541e7a7728bf2165c5f3ebc57679fb",
+				"img_logo_url": "9c8baddbab7938b5b995843d36526a30bd12bb1d",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 4920,
+				"name": "Natural Selection 2",
+				"playtime_forever": 0,
+				"img_icon_url": "df709ad4689cbfb82c2971be4adba431e755875f",
+				"img_logo_url": "ab7b1142e17865e6d3472d3fd4b345620ec5f36f",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 219950,
+				"name": "NiGHTS into Dreams...",
+				"playtime_forever": 0,
+				"img_icon_url": "630fb86750aaa5d9ca713df086fa93d9804e9f02",
+				"img_logo_url": "7316d46b1ce35a260ddedc6a1f7590a8b98dea92",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 4560,
+				"name": "Company of Heroes",
+				"playtime_forever": 0,
+				"img_icon_url": "64946619217da497c9b29bc817bb40dd7d28c912",
+				"img_logo_url": "e12e8695c6766b47a089351dd9c4531e669c2a7b"
+			},
+			{
+				"appid": 9340,
+				"name": "Company of Heroes: Opposing Fronts",
+				"playtime_forever": 0,
+				"img_icon_url": "29725d719946c3e1aa4eea15d262c9fd789c1392",
+				"img_logo_url": "830c99099ea2cfecfe74c41f376fc892a09dd181"
+			},
+			{
+				"appid": 20540,
+				"name": "Company of Heroes: Tales of Valor",
+				"playtime_forever": 0,
+				"img_icon_url": "64946619217da497c9b29bc817bb40dd7d28c912",
+				"img_logo_url": "ed0c55412acea558d025a3e238e2b7341edc5c41"
+			},
+			{
+				"appid": 43110,
+				"name": "Metro 2033",
+				"playtime_forever": 0,
+				"img_icon_url": "a70fe6dc214f24107d20596f3040dbfa220ed42d",
+				"img_logo_url": "df9a163ac1f28dfc84c93a6fc0dc51719eaef518",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 50620,
+				"name": "Darksiders",
+				"playtime_forever": 925,
+				"img_icon_url": "e429cee10d864faf2aae2ea9cd75e8e1942fbe08",
+				"img_logo_url": "14bd29bc9b291081b63258e3bfbbf5bb655c2347",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 55110,
+				"name": "Red Faction: Armageddon",
+				"playtime_forever": 0,
+				"img_icon_url": "e59c7e741c05c9071176b270bdbb733afe55c751",
+				"img_logo_url": "19f894d0e08dff8e284d4facc5968a1025da997d",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 228200,
+				"name": "Company of Heroes (New Steam Version)",
+				"playtime_forever": 0,
+				"img_icon_url": "df92dc239acb3cf5d3e3eba645f3df2aaf7f91ad",
+				"img_logo_url": "87aa009e93d5aa56a55d0e9056708d018ddd6483",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 201790,
+				"name": "Orcs Must Die! 2",
+				"playtime_forever": 0,
+				"img_icon_url": "fabd8658e8e76f7c99c56f26b69d29882756f9b4",
+				"img_logo_url": "c345d9b205f349f0e7f4e6cdf8af4d0b7d242505",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 4570,
+				"name": "Warhammer 40,000: Dawn of War - Game of the Year Edition",
+				"playtime_forever": 5,
+				"img_icon_url": "a4c7a8cce43d797c275aaf601d6855b90ba87769",
+				"img_logo_url": "2068980dca52521b069abc109f976d72ba0b1651",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71230,
+				"name": "Crazy Taxi",
+				"playtime_forever": 0,
+				"img_icon_url": "e71b220f8103e3515bd56de6a42395121e31e2cf",
+				"img_logo_url": "be180e020c4e1ca0a13ec1a9006a1235b6a9eb50",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71240,
+				"name": "SEGA Bass Fishing",
+				"playtime_forever": 0,
+				"img_icon_url": "fac67362e11293a673158e6d3c8c67693816868f",
+				"img_logo_url": "6255f428036c011b325b40ebf1c53daa4db7e1f1",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71250,
+				"name": "Sonic Adventure DX",
+				"playtime_forever": 0,
+				"img_icon_url": "6568d25b43e2d1d07fc16cbe3ac9278ca51c2fb3",
+				"img_logo_url": "e8374c63e76724af4648cdea5331f4ae39af4d06",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71260,
+				"name": "Space Channel 5: Part 2",
+				"playtime_forever": 366,
+				"img_icon_url": "82aec5f26e9d40c5275b1cd9bf692c4057c108ef",
+				"img_logo_url": "fad43b313c2f6869c42bf0d7c4959363c5394d9a",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 50650,
+				"name": "Darksiders II",
+				"playtime_forever": 1591,
+				"img_icon_url": "a2d5549090144f1bfd9e00f1b460c1ad0aa9c366",
+				"img_logo_url": "b0b8edfa57f332dc529c04b4dd2f5475227e71ac",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 35720,
+				"name": "Trine 2",
+				"playtime_forever": 0,
+				"img_icon_url": "061ecbbd7c70ae1c052377bad136c7759cbb708d",
+				"img_logo_url": "7d7c3b93bd85ad1db2a07f6cca01a767069c6407",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 226320,
+				"name": "Marvel Heroes 2015",
+				"playtime_forever": 0,
+				"img_icon_url": "a0c1c35208af7b63759361305631da48539d45cc",
+				"img_logo_url": "7121a66719963c4790d6169d38b9c65ad8f238bc",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 225260,
+				"name": "Brütal Legend",
+				"playtime_forever": 0,
+				"img_icon_url": "e3f25fba8538e5fb1ead751e767c2774df4fb0b4",
+				"img_logo_url": "cc8b60ac1fa649c950ff7a9881b98709b8372f94",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 210770,
+				"name": "Sanctum 2",
+				"playtime_forever": 0,
+				"img_icon_url": "4cdfa1d19be460374a111b718ce3a204f21ea1dc",
+				"img_logo_url": "333a8c65480bb85148bb3a185843a8520ae5d90f",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 234710,
+				"name": "Poker Night 2",
+				"playtime_forever": 7,
+				"img_icon_url": "b3073e6f089447a9cf1eeabf7579600061546322",
+				"img_logo_url": "0b274bb5ade23104ce267a05ce7ac0f7aaa0248d",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 31100,
+				"name": "Wallace & Gromit Ep 1: Fright of the Bumblebees",
+				"playtime_forever": 0,
+				"img_icon_url": "1c8b457c265e36e6ac08d8d5ae5709124eae3025",
+				"img_logo_url": "6b303e67e65d39cd3747ed21efb42de9ddb0d251"
+			},
+			{
+				"appid": 31110,
+				"name": "Wallace & Gromit Ep 2: The Last Resort",
+				"playtime_forever": 0,
+				"img_icon_url": "e6d415690e4c05b3d716030984346442f10e87e9",
+				"img_logo_url": "7cda224cf65955e5e763ce8eff0b099add72f04e"
+			},
+			{
+				"appid": 31120,
+				"name": "Wallace & Gromit Ep 3: Muzzled!",
+				"playtime_forever": 0,
+				"img_icon_url": "70475b4d75934174a0fff9969315be9a4993c150",
+				"img_logo_url": "3910a6ff5e48c5f7ed249b48387bc321504db73c"
+			},
+			{
+				"appid": 31130,
+				"name": "Wallace & Gromit Ep 4: The Bogey Man",
+				"playtime_forever": 0,
+				"img_icon_url": "9072b2096b4542529aa47f4115bff48ab781ff6e",
+				"img_logo_url": "8a5313cf2bdd01a0516c56b3ce952428de85d430"
+			},
+			{
+				"appid": 31220,
+				"name": "Sam & Max 301: The Penal Zone",
+				"playtime_forever": 335,
+				"img_icon_url": "2c9c4ac6dfa50c4c479b6b436f04974a372588f7",
+				"img_logo_url": "517196c999fe6316134332e749782154bde9adf5"
+			},
+			{
+				"appid": 31230,
+				"name": "Sam & Max 302: The Tomb of Sammun-Mak",
+				"playtime_forever": 72,
+				"img_icon_url": "e83fbb799f46b349586ca55fcf612350cc88ffe7",
+				"img_logo_url": "517196c999fe6316134332e749782154bde9adf5"
+			},
+			{
+				"appid": 31240,
+				"name": "Sam & Max 303: They Stole Max's Brain!",
+				"playtime_forever": 0,
+				"img_icon_url": "bf1ebfe347a80e2ac31577e0569de3aa201cd17f",
+				"img_logo_url": "517196c999fe6316134332e749782154bde9adf5"
+			},
+			{
+				"appid": 31250,
+				"name": "Sam & Max 304: Beyond the Alley of the Dolls",
+				"playtime_forever": 0,
+				"img_icon_url": "d4f834ac9d48cd59645f453d0cb30655dee6f629",
+				"img_logo_url": "62ef5af2ce55bb787ff490126c110c41131043bc"
+			},
+			{
+				"appid": 31260,
+				"name": "Sam & Max 305: The City that Dares not Sleep",
+				"playtime_forever": 0,
+				"img_icon_url": "9e41c6d0c777cd0a7fb4e96da4f20d2227841725",
+				"img_logo_url": "62ef5af2ce55bb787ff490126c110c41131043bc"
+			},
+			{
+				"appid": 31270,
+				"name": "Puzzle Agent",
+				"playtime_forever": 0,
+				"img_icon_url": "d0cae0b07b2512302968bd7625a9bf12cebdfba8",
+				"img_logo_url": "f1bd7dd0bae1026b17c61a605a567ed68e683fef"
+			},
+			{
+				"appid": 31280,
+				"name": "Poker Night at the Inventory",
+				"playtime_forever": 0,
+				"img_icon_url": "7d50bd1f5e7cfe68397e9ca0041836ad18153dfb",
+				"img_logo_url": "d962cde096bca06ee10d09880e9f3d6257941161",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 31290,
+				"name": "Back to the Future: Ep 1 - It's About Time",
+				"playtime_forever": 0,
+				"img_icon_url": "a9a9b1683209e3223779ad2315e4bf03e27619d7",
+				"img_logo_url": "252a22c149c29a2d93fcb0080f3ee9d2dbbd9a2f"
+			},
+			{
+				"appid": 94500,
+				"name": "Back to the Future: Ep 2 - Get Tannen!",
+				"playtime_forever": 0,
+				"img_icon_url": "d5382aedd7594e088a078341034e4b369210ec9a",
+				"img_logo_url": "ae0d863314d6111e6debaef7c9cdcf2940738b1e"
+			},
+			{
+				"appid": 94510,
+				"name": "Back to the Future: Ep 3 - Citizen Brown",
+				"playtime_forever": 0,
+				"img_icon_url": "a51c4795b44f689628bd76bc64cad310385ba1a2",
+				"img_logo_url": "7fe46585ad7fbc8fedb38db7f8dd8608be5a46ee"
+			},
+			{
+				"appid": 94520,
+				"name": "Back to the Future: Ep 4 - Double Visions",
+				"playtime_forever": 0,
+				"img_icon_url": "5a7fd98c15742b9fca4e443b5eaadf953a6c83d3",
+				"img_logo_url": "ac9fc7c15ae656d200299003ce22ab84185e54e4"
+			},
+			{
+				"appid": 94530,
+				"name": "Back to the Future: Ep 5 - OUTATIME",
+				"playtime_forever": 0,
+				"img_icon_url": "3d034831533383bc5a58787763925660684de8c4",
+				"img_logo_url": "76361dfc1ef09dbb7f6572a6da7ab38a811f54af"
+			},
+			{
+				"appid": 94590,
+				"name": "Puzzle Agent 2",
+				"playtime_forever": 0,
+				"img_icon_url": "d558eb6bddeb55f5f145822f3949ab50bc02aff9",
+				"img_logo_url": "b7aac2e076fb1c5178681e2cab0f8bae4380c96d",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 94600,
+				"name": "Hector: Ep 1",
+				"playtime_forever": 0,
+				"img_icon_url": "aa0a113e80b8cdeff47a523a87dd2fad1f43d73e",
+				"img_logo_url": "fae3324a5c43647dda98be23bf1db4480c031273"
+			},
+			{
+				"appid": 94610,
+				"name": "Hector: Ep 2",
+				"playtime_forever": 0,
+				"img_icon_url": "0bfad503074efc1c46755d05d36be4755945f8fe",
+				"img_logo_url": "52a3e61842a22bf75f6bf6d355400d5b3776f9b4"
+			},
+			{
+				"appid": 94620,
+				"name": "Hector: Ep 3",
+				"playtime_forever": 0,
+				"img_icon_url": "aa0a113e80b8cdeff47a523a87dd2fad1f43d73e",
+				"img_logo_url": "97ec609986c7672a3928e7dca14d9aead4cbf65f"
+			},
+			{
+				"appid": 236090,
+				"name": "Dust: An Elysian Tail",
+				"playtime_forever": 563,
+				"img_icon_url": "3779535aba1ad565d504a7d52c6dd5c9eeb47fb2",
+				"img_logo_url": "544fd60b00696d8c3402828da7055fea64d619ca",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 229480,
+				"name": "Dungeons & Dragons: Chronicles of Mystara",
+				"playtime_forever": 91,
+				"img_icon_url": "270699bf34b75a6789370de8b0cb98e163832f71",
+				"img_logo_url": "cb7b16b064562469c375a22d9d07a7ab11abdab6",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 208610,
+				"name": "Skullgirls ∞Endless Beta∞",
+				"playtime_forever": 292,
+				"img_icon_url": "7bf859db736b8825045b0cc79acc4bb7be8cd7b9",
+				"img_logo_url": "33974b81779c888b3b4d9c4b91d86ef0907b11f3",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 237110,
+				"name": "Mortal Kombat Komplete Edition",
+				"playtime_forever": 365,
+				"img_icon_url": "3b9c627b90f42cf650d5848e2fdd779fa4e6eb19",
+				"img_logo_url": "307dc1eacffd54e5a7a02b663cec1c5105059811",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 245170,
+				"name": "Skullgirls",
+				"playtime_forever": 1152,
+				"img_icon_url": "7bf859db736b8825045b0cc79acc4bb7be8cd7b9",
+				"img_logo_url": "ca3f7bd4fbb3cf73855ebce91b6dafc2104d651b",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 222940,
+				"name": "THE KING OF FIGHTERS XIII STEAM EDITION",
+				"playtime_forever": 322,
+				"img_icon_url": "de8d9bf86ae8983464d69743b55cef3992330ccf",
+				"img_logo_url": "9f2bec35f18bfc1a80ffab64bc51a09a880343b6",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 250760,
+				"name": "Shovel Knight",
+				"playtime_forever": 1,
+				"img_icon_url": "9b8866653bcaf20db1424653df8560205939cdba",
+				"img_logo_url": "23fca16e3df2ed731136574b320988406eb0f712",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 250900,
+				"name": "The Binding of Isaac: Rebirth",
+				"playtime_forever": 95,
+				"img_icon_url": "16d46c8630499bfc54d20745ac90786a302cd643",
+				"img_logo_url": "c7a76988c53e7f3a3aa1cf224aaf4dbd067ebbf9",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 111900,
+				"name": "Guardians of Middle-earth",
+				"playtime_forever": 0,
+				"img_icon_url": "5ab636ac90b8476892d6e0ae377624d5b934f600",
+				"img_logo_url": "08a7116bebd1bf44bb8e86495358dca14224d223",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 234670,
+				"name": "NARUTO SHIPPUDEN: Ultimate Ninja STORM 3 Full Burst",
+				"playtime_forever": 1405,
+				"img_icon_url": "ddd956cc6ec3370449f96298653d4119c5666fff",
+				"img_logo_url": "12895039c12ec92be72faa2d13acb88886b8cb97",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 42910,
+				"name": "Magicka",
+				"playtime_forever": 0,
+				"img_icon_url": "0eb97d0cd644ee08b1339d2160c7a6adf2ea0a65",
+				"img_logo_url": "8c59c674ef40f59c3bafde8ff0d59b7994c66477",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 212480,
+				"name": "Sonic & All-Stars Racing Transformed",
+				"playtime_forever": 0,
+				"img_icon_url": "95767af7b08d7ecebf1e9cb1ed1c92c98e4c084f",
+				"img_logo_url": "351603b89e1863831c84aacab7bf3a315f03443b",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 261640,
+				"name": "Borderlands: The Pre-Sequel",
+				"playtime_2weeks": 838,
+				"playtime_forever": 1157,
+				"img_icon_url": "af5ef05eac8b1eb618e4f57354ac7b3e918ab1bd",
+				"img_logo_url": "df64c72fd335a03dbcc0a19b1f81acc8db1b94ba",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 39150,
+				"name": "FINAL FANTASY VIII",
+				"playtime_forever": 119,
+				"img_icon_url": "e2b0371cd72160603e7ecaaf95b238a46ba254e6",
+				"img_logo_url": "0c912769e975586cdcfe4a6b008d538f1f96a032",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 235460,
+				"name": "METAL GEAR RISING: REVENGEANCE",
+				"playtime_forever": 1268,
+				"img_icon_url": "ad0f84fe48b57f3861b6c6d743f26b98d670c21f",
+				"img_logo_url": "a21384421dafa03783e3672a5f4754f70e63235e",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 550,
+				"name": "Left 4 Dead 2",
+				"playtime_forever": 0,
+				"img_icon_url": "7d5a243f9500d2f8467312822f8af2a2928777ed",
+				"img_logo_url": "205863cc21e751a576d6fff851984b3170684142",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 236430,
+				"name": "DARK SOULS™ II",
+				"playtime_forever": 8872,
+				"img_icon_url": "8d5b3da903efb047d4efb670c08714a4d1071e83",
+				"img_logo_url": "d16871e0aa9196e5e7d865f76fbed278a0309e85",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 282900,
+				"name": "Hyperdimension Neptunia Re;Birth1",
+				"playtime_forever": 1647,
+				"img_icon_url": "0cd228210df4f44ef8e77f62b18d1a9af81a72d4",
+				"img_logo_url": "c2835cfa39dbaf8e7e1f668e4bf491855a274947",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 254700,
+				"name": "resident evil 4 / biohazard 4",
+				"playtime_forever": 737,
+				"img_icon_url": "535bfea3332662271f1e3a972832bc0b4aba5a38",
+				"img_logo_url": "532d72710af44f29cc123c5796e95e0382461ee5",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 231430,
+				"name": "Company of Heroes 2",
+				"playtime_forever": 0,
+				"img_icon_url": "9efafff369d37ea19c44139de4476e6c63319b6b",
+				"img_logo_url": "2c413e4cc731862e0b3307ed9c23b1cd20087130",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 317170,
+				"name": "Company of Heroes 2 - Beta",
+				"playtime_forever": 0,
+				"img_icon_url": "9efafff369d37ea19c44139de4476e6c63319b6b",
+				"img_logo_url": "62afc50b5f0970c1070951f56a7dd0c0b943b013",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 294810,
+				"name": "BlazBlue: Continuum Shift Extend",
+				"playtime_forever": 82,
+				"img_icon_url": "244644a6721480f40e4de61e4bb7a337d999e435",
+				"img_logo_url": "b7105e9443e1f3bed7bb3fd1599a140e75dcf2c6",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 294860,
+				"name": "Valkyria Chronicles™",
+				"playtime_forever": 65,
+				"img_icon_url": "176c6dcafc9bf0fbb87f9adeb224df88c8248a66",
+				"img_logo_url": "08316e1d6a45d8e13de7f5e1a1480cf4efff15cf",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 285440,
+				"name": "Crimzon Clover  WORLD IGNITION",
+				"playtime_forever": 8,
+				"img_icon_url": "8f4f6490c9b48e8d6e2b688c4a097f9bdd8fb56d",
+				"img_logo_url": "72ab0aac6800b9ec9f79571d6f425f0e687d04ca",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 314030,
+				"name": "Guilty Gear X2 #Reload",
+				"playtime_forever": 99,
+				"img_icon_url": "bde7b6e8d891b310fad62d25a0cf009c979db84c",
+				"img_logo_url": "94edca39fa971bc8beeb0066afc99993246a9976"
+			},
+			{
+				"appid": 206420,
+				"name": "Saints Row IV",
+				"playtime_forever": 205,
+				"img_icon_url": "b5e8448a3e2ea31ddf3595addae4e1eee2375c0d",
+				"img_logo_url": "49d796621c286130a8ddeea918d9aae8c8441455",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 21690,
+				"name": "Resident Evil 5 / Biohazard 5",
+				"playtime_forever": 782,
+				"img_icon_url": "26108f5caff3638c9f522dd79ee84a12761f373a",
+				"img_logo_url": "e277ab70fff98bb2300a39bf8e2371a746fe50b1",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 222480,
+				"name": "Resident Evil Revelations / Biohazard Revelations UE",
+				"playtime_forever": 476,
+				"img_icon_url": "5725845fe83f846a04135034c5be55aef008c725",
+				"img_logo_url": "cf242207e0e06251f55baf2f89c37ded12c79329",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 323470,
+				"name": "DRAGON BALL XENOVERSE",
+				"playtime_2weeks": 24,
+				"playtime_forever": 815,
+				"img_icon_url": "810b2bab6e3197b5d63d3abffcebafaac8dc6312",
+				"img_logo_url": "f8724eeddf94534d66b8057cf770a9cd8318a14a",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 730,
+				"name": "Counter-Strike: Global Offensive",
+				"playtime_forever": 62,
+				"img_icon_url": "69f7ebe2735c366c65c0b33dae00e12dc40edbe4",
+				"img_logo_url": "d0595ff02f5c79fd19b06f4d6165c3fda2372820",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 222440,
+				"name": "THE KING OF FIGHTERS 2002 UNLIMITED MATCH",
+				"playtime_2weeks": 1,
+				"playtime_forever": 1,
+				"img_icon_url": "c9235efbfa66ad95a6ece092a7860ca8b92cfa6f",
+				"img_logo_url": "787a8b76a5c9348784f50798403b2672e488c557",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 247000,
+				"name": "Talisman: Digital Edition",
+				"playtime_forever": 0,
+				"img_icon_url": "ab50e24b04d5fa8faf219fe622199061b57bcf20",
+				"img_logo_url": "73b7daee45a29a5dfe5c0efef72223943bf8722f",
+				"has_community_visible_stats": true
+			}]
+        self.assertEqual(gamesPulling(steamnum,APIKEY),jsonList)

+ 31 - 0
hackathon_starter/hackathon/unittests/testtumblr.py

@@ -0,0 +1,31 @@
+import unittest
+from mock import Mock, patch, MagicMock
+from hackathon.scripts.tumblr import *
+import oauth2
+import urlparse
+from django.conf import settings
+
+class TestTumblr(unittest.TestCase):
+
+	def setUp(self):
+		self.consumer_key = 'KrSbAc9cYLmIgVAn1D21FjRR97QWsutNMxkPDFBxo8CMWtMk4M'
+		self.consumer_secret = 'lKWMtL2Lj8zr5pY51PVqT8ugeoG0DjrdgoFewM0QTSyJ12jP8d'
+		self.consumer = oauth2.Consumer(key=self.consumer_key, secret=self.consumer_secret)
+		self.tumblrclient = TumblrOauthClient(self.consumer_key, self.consumer_secret, 'QBXdeeMKAnLzDbIG7dDNewTzRYyQoHZLbcn3bAFTCEFF5EXurl')
+		self.authorize = self.tumblrclient.get_authorize_url()
+
+		
+	def test_init(self):
+		self.assertEqual(self.consumer.key, self.consumer_key)
+		self.assertEqual(self.consumer.secret, self.consumer_secret)
+
+	def test_get_authorize_url(self):
+		self.client = oauth2.Client(self.consumer)
+		self.assertEqual(self.client.consumer, self.consumer)
+		with patch('hackathon.scripts.tumblr.TumblrOauthClient.get_authorize_url') as mock_get_authorize_url:
+			mock_get_authorize_url.return_value = "oauth_token=QBXdeeMKAnLzDbIG7dDNewTzRYyQoHZLbcn3bAFTCEFF5EXurl&oauth_token_secret=u10SuRl2nzS8vFK4K7UPQexAvbIFBFrZBjA79XDlgoXFxv9ZhO&oauth_callback_confirmed=true"
+			self.request_token = dict(urlparse.parse_qsl(mock_get_authorize_url.return_value))
+			self.oauth_token = self.request_token['oauth_token']
+			self.oauth_token_secret = self.request_token['oauth_token_secret']		
+			link = "http://www.tumblr.com/oauth/authorize?oauth_token="+self.oauth_token+"&redirect_uri=http%3A%2F%2Flocalhost%3A8000/hackathon/tumblr"
+			self.assertEqual(self.authorize,link )

+ 21 - 0
hackathon_starter/hackathon/urls.py

@@ -0,0 +1,21 @@
+from django.conf.urls import patterns, url
+
+from hackathon import views
+
+urlpatterns = patterns('',
+    url(r'^$', views.index, name='index'),
+    url(r'^register/$', views.register, name='register'),
+    url(r'^login/$', views.user_login, name='login'),
+    url(r'^logout/$', views.user_logout, name='logout'),
+    url(r'^api/$', views.api_examples, name='api'),
+    url(r'^steam/$', views.steam, name='steam'),
+    url(r'^githubResume/$', views.githubResume, name='githubResume'),
+    url(r'^githubUser/$', views.githubUser, name='githubUser'),
+    url(r'^githubTopRepositories/$', views.githubTopRepositories, name='githubTopRepositories'),
+    url(r'^tumblr/$', views.tumblr, name='tumblr'),
+    url(r'^linkedin/$', views.linkedin, name='linkedin'),
+    url(r'^snippets/$', views.snippet_list, name='snippets'),
+    url(r'^twilio/$', views.twilio, name='twilio'),
+    url(r'^instagram/$', views.instagram, name='instagram'),
+    url(r'^instagram_login/$', views.instagram_login, name='instagram_login'),
+)

+ 256 - 0
hackathon_starter/hackathon/views.py

@@ -0,0 +1,256 @@
+# Django
+from django.shortcuts import render
+from django.contrib.auth import logout
+from django.template import RequestContext, loader
+from django.contrib.auth import authenticate, login
+from django.http import HttpResponse, HttpResponseRedirect
+from django.conf import settings
+from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.models import User
+from django.contrib.auth.decorators import login_required
+from django.views.decorators.csrf import csrf_exempt
+from django.http import JsonResponse
+
+# Scripts
+from scripts.steam import gamesPulling, steamIDPulling 
+from scripts.github import *
+from scripts.tumblr import TumblrOauthClient
+from scripts.twilioapi import *
+from scripts.instagram import InstagramOauthClient
+
+# Python
+import oauth2 as oauth
+from rest_framework.renderers import JSONRenderer
+from rest_framework.parsers import JSONParser
+
+# Models
+from hackathon.models import Snippet, Profile
+from hackathon.serializers import SnippetSerializer
+from hackathon.forms import UserForm
+
+
+getTumblr = TumblrOauthClient(settings.TUMBLR_CONSUMER_KEY, settings.TUMBLR_CONSUMER_SECRET)
+getInstagram = InstagramOauthClient(settings.INSTAGRAM_CLIENT_ID, settings.INSTAGRAM_CLIENT_SECRET)
+
+def index(request):
+    context = {'hello': 'world'}
+    return render(request, 'hackathon/index.html', context)
+
+##################
+#   Twilio API   #
+##################
+
+def twilio(request):
+    sendSMS('Meow', '+13473282978', '+13473781813')
+    return render(request, 'hackathon/twilio.html')
+
+##################
+#  API Examples  #
+##################
+
+def api_examples(request):
+    instagram_url =getInstagram.get_authorize_url()
+    if not getTumblr.accessed:
+        obtain_oauth_verifier = getTumblr.authorize_url()
+    else:
+        obtain_oauth_verifier = '/hackathon/tumblr'
+    context = {'title': 'API Examples Page', 'tumblr_url': obtain_oauth_verifier, 'instagram_url':instagram_url}
+    return render(request, 'hackathon/api_examples.html', context)
+
+#################
+#   STEAM API   #
+#################
+
+def steam(request):
+    #Should link to test of Steam API example.
+    key = '231E98D442E52B87110816C3D5114A1D'
+    SteamUN = "Marorin"
+    steamID = steamIDPulling(SteamUN, key)
+    game = gamesPulling(steamID, key)
+    return render(request,'hackathon/steam.html', {"game": game })
+
+
+#################
+#   GITHUB API  #
+#################
+
+
+def githubUser(request):
+    '''Returns JSON response about a specific Github User'''
+
+    parsedData = {}
+    parsedData['userData'] = getUserData(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    return JsonResponse({ 'data': parsedData })
+
+def githubTopRepositories(request):
+    '''Returns JSON response of a User's Top Committed repositories'''
+
+    parsedData = {}
+    repositories = getUserRepositories(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    list = getTopContributedRepositories(repositories, settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    filtered = filterCommits(list)
+    parsedData['committed'] = filtered
+    return JsonResponse({ 'data': parsedData })
+
+def githubResume(request):
+    '''A sample application which pulls various Github data to form a Resume of sorts'''
+    
+    allData = {}
+    userData = getUserData(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    repositories = getUserRepositories(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    list = getTopContributedRepositories(repositories, settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    filtered = filterCommits(list)
+    stargazers = getStarGazerCount(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    filteredStargazers = filterStarGazerCount(stargazers)
+    forkedRepos = getForkedRepositories(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    allData['userData'] = userData
+    allData['filteredData'] = filtered
+    allData['filteredStargazers'] = filteredStargazers
+    allData['forkedRepos'] = forkedRepos
+    return render(request, 'hackathon/github.html', { 'data': allData })
+
+
+#################
+#   TUMBLR API  #
+#################
+
+def tumblr(request):
+    ''' Tumblr api calls '''
+    #retrieve verifier via url link
+    #if not request.GET.items():
+    #    return HttpResponseRedirect('/hackathon/api/')
+    if not getTumblr.accessed:
+        oauth_verifier = request.GET.get('oauth_verifier')
+        getTumblr.access_token_url(oauth_verifier)
+    #get blogger twitterthecomic's blog information
+    blog = getTumblr.getBlogInfo('twitterthecomic')
+    #get tags that was tagged along starbucks
+    tagged_blog = getTumblr.getTaggedInfo("starbucks")
+    #get blog information tagged with starbucks
+    blogontag = getTumblr.getTaggedBlog("starbucks")
+    #get user's information
+    userinfo, total_blog = getTumblr.getUserInfo()
+    context = {'title': "What's up Starbucks?", 'blogData': blog, 'blogTag': tagged_blog, 'blogontag': blogontag, 'userinfo': userinfo, 'total_blog':total_blog}
+    return render(request, 'hackathon/tumblr.html', context)
+
+
+####################
+#   INSTAGRAM API  #
+####################
+
+def instagram(request):
+    code = request.GET['code']
+    getInstagram.get_access_token(code)
+
+    if request.user not in User.objects.all():
+        try:  
+            user = User.objects.get(username=getInstagram.user_data['username'] )
+        except User.DoesNotExist:
+            username = getInstagram.user_data['username']
+            new_user = User.objects.create_user(username, username+'@example.com', 'password')
+            new_user.save()
+            profile = Profile()
+            profile.user = new_user
+            profile.oauth_token = getInstagram.client_id
+            profile.oauth_secret = getInstagram.client_secret
+            profile.save()
+
+        user = authenticate(username=getInstagram.user_data['username'], password='password')
+        login(request, user)
+
+    search_tag = 'kitten'
+    #return tagged objects
+    tagged_media = getInstagram.get_tagged_media(search_tag)
+    #user =  getInstagram.user_data['username']
+    #print User.objects.get(username=user)
+
+    context = {'title': 'Instagram', 'tagged_media': tagged_media, 'search_tag': search_tag}
+    return render(request, 'hackathon/instagram.html', context)
+
+##################
+#  LINKED IN API #
+##################
+
+def linkedin(request):
+    userinfo = getUserInfo()
+    context = {'title': 'linkedin Example','userdata': userinfo}
+    return render(request, 'hackathon/linkedin.html', context)
+
+
+#########################
+# Snippet RESTful Model #
+#########################
+
+class JSONResponse(HttpResponse):
+    """
+    An HttpResponse that renders its content into JSON.
+    """
+    def __init__(self, data, **kwargs):
+        content = JSONRenderer().render(data)
+        kwargs['content_type'] = 'application/json'
+        super(JSONResponse, self).__init__(content, **kwargs)
+
+@csrf_exempt
+def snippet_list(request):
+    """
+    List all code snippets, or create a new snippet.
+    """
+    if request.method == 'GET':
+        snippets = Snippet.objects.all()
+        serializer = SnippetSerializer(snippets, many=True)
+        return JSONResponse(serializer.data)
+
+
+######################
+# Registration Views #
+######################
+
+def register(request):
+    registered = False
+    if request.method == 'POST':
+        user_form = UserForm(data=request.POST)
+        if user_form.is_valid():
+            user = user_form.save()
+            user.set_password(user.password)
+            user.save()
+            registered = True
+        else:
+            print user_form.errors
+    else:
+        user_form = UserForm()
+
+    
+    return render(request,
+            'hackathon/register.html',
+            {'user_form': user_form, 'registered': registered} )
+
+def user_login(request):
+    if request.method == 'POST':
+        username = request.POST.get('username')
+        password = request.POST.get('password')
+
+
+        user = authenticate(username=username, password=password)
+
+
+        if user:
+            if user.is_active:
+                login(request, user)
+                return HttpResponseRedirect('/hackathon/')
+            else:
+                return HttpResponse("Your Django Hackathon account is disabled.")
+        else:
+            print "Invalid login details: {0}, {1}".format(username, password)
+            return HttpResponse("Invalid login details supplied.")
+
+    else:
+        return render(request, 'hackathon/login.html', {})
+
+def user_logout(request):
+    logout(request)
+    return HttpResponseRedirect('/hackathon/')
+
+
+def instagram_login(request):
+    instagram_url =getInstagram.get_authorize_url()
+    return HttpResponseRedirect(instagram_url)

+ 0 - 0
hackathon_starter/hackathon_starter/__init__.py


+ 118 - 0
hackathon_starter/hackathon_starter/settings.py

@@ -0,0 +1,118 @@
+"""
+Django settings for hackathon_starter project.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.7/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/1.7/ref/settings/
+"""
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+import os
+BASE_DIR = os.path.dirname(os.path.dirname(__file__))
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'keuhh=0*%do-ayvy*m2k=vss*$7)j8q!@u0+d^na7mi2(^!l!d'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+TEMPLATE_DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = (
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'hackathon',
+    'bootstrapform',
+    # 'django_openid',
+    'django_nose',
+    'rest_framework',
+    'corsheaders',
+)
+
+MIDDLEWARE_CLASSES = (
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'corsheaders.middleware.CorsMiddleware',
+    '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',
+    #'django_openid_consumer.SessionConsumer',
+)
+
+ROOT_URLCONF = 'hackathon_starter.urls'
+
+WSGI_APPLICATION = 'hackathon_starter.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+    }
+}
+
+# Internationalization
+# https://docs.djangoproject.com/en/1.7/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/1.7/howto/static-files/
+
+STATIC_URL = '/static/'
+
+TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
+
+# Use nose to run all tests
+TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
+
+# Tell nose to measure coverage on the 'foo' and 'bar' apps
+NOSE_ARGS = [
+    '--with-coverage',
+    '--cover-package=hackathon/scripts',
+]
+
+CORS_ORIGIN_ALLOW_ALL = True
+
+############
+#   KEYS   #
+############
+
+GITHUB_CLIENT_ID = 'client_id=2404a1e21aebd902f6db'
+GITHUB_CLIENT_SECRET = 'client_secret=3da44769d4b7c9465fa4c812669148a163607c23'
+TUMBLR_CONSUMER_KEY = 'KrSbAc9cYLmIgVAn1D21FjRR97QWsutNMxkPDFBxo8CMWtMk4M'
+TUMBLR_CONSUMER_SECRET ='lKWMtL2Lj8zr5pY51PVqT8ugeoG0DjrdgoFewM0QTSyJ12jP8d'
+TWITTER_TOKEN = 'F05dgLAzHEOalb4K2xDQ8Umm8'
+TWITTER_SECRET = 'Yy3a74Z7gvyhxRruJsvUtUl8uK8iv6qKkVqbZSijUxK71Z1qTY'
+INSTAGRAM_CLIENT_ID = '77dc10b9e3624e908ce437c0a82da92e'
+INSTAGRAM_CLIENT_SECRET = '8bcf3139857149aaba7acaa61288427f'
+

+ 8 - 0
hackathon_starter/hackathon_starter/urls.py

@@ -0,0 +1,8 @@
+from django.conf.urls import patterns, include, url
+from django.contrib import admin
+
+urlpatterns = patterns('',
+    url(r'^hackathon/', include('hackathon.urls')),
+    url(r'^admin/', include(admin.site.urls)),
+    # url(r'^openid/(.*)', SessionConsumer()),
+)

+ 14 - 0
hackathon_starter/hackathon_starter/wsgi.py

@@ -0,0 +1,14 @@
+"""
+WSGI config for hackathon_starter 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.7/howto/deployment/wsgi/
+"""
+
+import os
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hackathon_starter.settings")
+
+from django.core.wsgi import get_wsgi_application
+application = get_wsgi_application()

+ 10 - 0
hackathon_starter/manage.py

@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hackathon_starter.settings")
+
+    from django.core.management import execute_from_command_line
+
+    execute_from_command_line(sys.argv)

+ 3 - 0
ionic/.bowerrc

@@ -0,0 +1,3 @@
+{
+  "directory": "www/lib"
+}

+ 6 - 0
ionic/.gitignore

@@ -0,0 +1,6 @@
+# Specifies intentionally untracked files to ignore when using Git
+# http://git-scm.com/docs/gitignore
+
+node_modules/
+platforms/
+plugins/

+ 26 - 0
ionic/README.md

@@ -0,0 +1,26 @@
+Ionic App Base
+=====================
+
+A starting project for Ionic that optionally supports using custom SCSS.
+
+## Using this project
+
+We recommend using the [Ionic CLI](https://github.com/driftyco/ionic-cli) to create new Ionic projects that are based on this project but use a ready-made starter template.
+
+For example, to start a new Ionic project with the default tabs interface, make sure the `ionic` utility is installed:
+
+```bash
+$ npm install -g ionic
+```
+
+Then run:
+
+```bash
+$ ionic start myProject tabs
+```
+
+More info on this can be found on the Ionic [Getting Started](http://ionicframework.com/getting-started) page and the [Ionic CLI](https://github.com/driftyco/ionic-cli) repo.
+
+## Issues
+Issues have been disabled on this repo, if you do find an issue or have a question consider posting it on the [Ionic Forum](http://forum.ionicframework.com/).  Or else if there is truly an error, follow our guidelines for [submitting an issue](http://ionicframework.com/submit-issue/) to the main Ionic repository.
+

+ 7 - 0
ionic/bower.json

@@ -0,0 +1,7 @@
+{
+  "name": "HelloIonic",
+  "private": "true",
+  "devDependencies": {
+    "ionic": "driftyco/ionic-bower#1.0.0-rc.2"
+  }
+}

+ 49 - 0
ionic/config.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<widget id="com.ionicframework.starter" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+  <name>HelloCordova</name>
+  <description>
+        An Ionic Framework and Cordova project.
+    </description>
+  <author email="hi@ionicframework" href="http://ionicframework.com/">
+      Ionic Framework Team
+    </author>
+  <content src="index.html"/>
+  <access origin="*"/>
+  <preference name="webviewbounce" value="false"/>
+  <preference name="UIWebViewBounce" value="false"/>
+  <preference name="DisallowOverscroll" value="true"/>
+  <preference name="BackupWebStorage" value="none"/>
+  <preference name="SplashScreen" value="screen"/>
+  <preference name="SplashScreenDelay" value="3000"/>
+  <feature name="StatusBar">
+    <param name="ios-package" value="CDVStatusBar" onload="true"/>
+  </feature>
+  <platform name="ios">
+    <icon src="resources/ios/icon/icon.png" width="57" height="57"/>
+    <icon src="resources/ios/icon/icon@2x.png" width="114" height="114"/>
+    <icon src="resources/ios/icon/icon-40.png" width="40" height="40"/>
+    <icon src="resources/ios/icon/icon-40@2x.png" width="80" height="80"/>
+    <icon src="resources/ios/icon/icon-50.png" width="50" height="50"/>
+    <icon src="resources/ios/icon/icon-50@2x.png" width="100" height="100"/>
+    <icon src="resources/ios/icon/icon-60.png" width="60" height="60"/>
+    <icon src="resources/ios/icon/icon-60@2x.png" width="120" height="120"/>
+    <icon src="resources/ios/icon/icon-60@3x.png" width="180" height="180"/>
+    <icon src="resources/ios/icon/icon-72.png" width="72" height="72"/>
+    <icon src="resources/ios/icon/icon-72@2x.png" width="144" height="144"/>
+    <icon src="resources/ios/icon/icon-76.png" width="76" height="76"/>
+    <icon src="resources/ios/icon/icon-76@2x.png" width="152" height="152"/>
+    <icon src="resources/ios/icon/icon-small.png" width="29" height="29"/>
+    <icon src="resources/ios/icon/icon-small@2x.png" width="58" height="58"/>
+    <icon src="resources/ios/icon/icon-small@3x.png" width="87" height="87"/>
+    <splash src="resources/ios/splash/Default-568h@2x~iphone.png" height="1136" width="640"/>
+    <splash src="resources/ios/splash/Default-667h.png" height="1334" width="750"/>
+    <splash src="resources/ios/splash/Default-736h.png" height="2208" width="1242"/>
+    <splash src="resources/ios/splash/Default-Landscape-736h.png" height="1242" width="2208"/>
+    <splash src="resources/ios/splash/Default-Landscape@2x~ipad.png" height="1536" width="2048"/>
+    <splash src="resources/ios/splash/Default-Landscape~ipad.png" height="768" width="1024"/>
+    <splash src="resources/ios/splash/Default-Portrait@2x~ipad.png" height="2048" width="1536"/>
+    <splash src="resources/ios/splash/Default-Portrait~ipad.png" height="1024" width="768"/>
+    <splash src="resources/ios/splash/Default@2x~iphone.png" height="960" width="640"/>
+    <splash src="resources/ios/splash/Default~iphone.png" height="480" width="320"/>
+  </platform>
+</widget>

+ 50 - 0
ionic/gulpfile.js

@@ -0,0 +1,50 @@
+var gulp = require('gulp');
+var gutil = require('gulp-util');
+var bower = require('bower');
+var concat = require('gulp-concat');
+var sass = require('gulp-sass');
+var minifyCss = require('gulp-minify-css');
+var rename = require('gulp-rename');
+var sh = require('shelljs');
+
+var paths = {
+  sass: ['./scss/**/*.scss']
+};
+
+gulp.task('default', ['sass']);
+
+gulp.task('sass', function(done) {
+  gulp.src('./scss/ionic.app.scss')
+    .pipe(sass())
+    .pipe(gulp.dest('./www/css/'))
+    .pipe(minifyCss({
+      keepSpecialComments: 0
+    }))
+    .pipe(rename({ extname: '.min.css' }))
+    .pipe(gulp.dest('./www/css/'))
+    .on('end', done);
+});
+
+gulp.task('watch', function() {
+  gulp.watch(paths.sass, ['sass']);
+});
+
+gulp.task('install', ['git-check'], function() {
+  return bower.commands.install()
+    .on('log', function(data) {
+      gutil.log('bower', gutil.colors.cyan(data.id), data.message);
+    });
+});
+
+gulp.task('git-check', function(done) {
+  if (!sh.which('git')) {
+    console.log(
+      '  ' + gutil.colors.red('Git is not installed.'),
+      '\n  Git, the version control system, is required to download Ionic.',
+      '\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
+      '\n  Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
+    );
+    process.exit(1);
+  }
+  done();
+});

+ 83 - 0
ionic/hooks/README.md

@@ -0,0 +1,83 @@
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+# Cordova Hooks
+
+This directory may contain scripts used to customize cordova commands. This
+directory used to exist at `.cordova/hooks`, but has now been moved to the
+project root. Any scripts you add to these directories will be executed before
+and after the commands corresponding to the directory name. Useful for
+integrating your own build systems or integrating with version control systems.
+
+__Remember__: Make your scripts executable.
+
+## Hook Directories
+The following subdirectories will be used for hooks:
+
+    after_build/
+    after_compile/
+    after_docs/
+    after_emulate/
+    after_platform_add/
+    after_platform_rm/
+    after_platform_ls/
+    after_plugin_add/
+    after_plugin_ls/
+    after_plugin_rm/
+    after_plugin_search/
+    after_prepare/
+    after_run/
+    after_serve/
+    before_build/
+    before_compile/
+    before_docs/
+    before_emulate/
+    before_platform_add/
+    before_platform_rm/
+    before_platform_ls/
+    before_plugin_add/
+    before_plugin_ls/
+    before_plugin_rm/
+    before_plugin_search/
+    before_prepare/
+    before_run/
+    before_serve/
+    pre_package/ <-- Windows 8 and Windows Phone only.
+
+## Script Interface
+
+All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:
+
+* CORDOVA_VERSION - The version of the Cordova-CLI.
+* CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
+* CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
+* CORDOVA_HOOK - Path to the hook that is being executed.
+* CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
+
+If a script returns a non-zero exit code, then the parent cordova command will be aborted.
+
+
+## Writing hooks
+
+We highly recommend writting your hooks using Node.js so that they are
+cross-platform. Some good examples are shown here:
+
+[http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)
+

+ 94 - 0
ionic/hooks/after_prepare/010_add_platform_class.js

@@ -0,0 +1,94 @@
+#!/usr/bin/env node
+
+// Add Platform Class
+// v1.0
+// Automatically adds the platform class to the body tag
+// after the `prepare` command. By placing the platform CSS classes
+// directly in the HTML built for the platform, it speeds up
+// rendering the correct layout/style for the specific platform
+// instead of waiting for the JS to figure out the correct classes.
+
+var fs = require('fs');
+var path = require('path');
+
+var rootdir = process.argv[2];
+
+function addPlatformBodyTag(indexPath, platform) {
+  // add the platform class to the body tag
+  try {
+    var platformClass = 'platform-' + platform;
+    var cordovaClass = 'platform-cordova platform-webview';
+
+    var html = fs.readFileSync(indexPath, 'utf8');
+
+    var bodyTag = findBodyTag(html);
+    if(!bodyTag) return; // no opening body tag, something's wrong
+
+    if(bodyTag.indexOf(platformClass) > -1) return; // already added
+
+    var newBodyTag = bodyTag;
+
+    var classAttr = findClassAttr(bodyTag);
+    if(classAttr) {
+      // body tag has existing class attribute, add the classname
+      var endingQuote = classAttr.substring(classAttr.length-1);
+      var newClassAttr = classAttr.substring(0, classAttr.length-1);
+      newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
+      newBodyTag = bodyTag.replace(classAttr, newClassAttr);
+
+    } else {
+      // add class attribute to the body tag
+      newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
+    }
+
+    html = html.replace(bodyTag, newBodyTag);
+
+    fs.writeFileSync(indexPath, html, 'utf8');
+
+    process.stdout.write('add to body class: ' + platformClass + '\n');
+  } catch(e) {
+    process.stdout.write(e);
+  }
+}
+
+function findBodyTag(html) {
+  // get the body tag
+  try{
+    return html.match(/<body(?=[\s>])(.*?)>/gi)[0];
+  }catch(e){}
+}
+
+function findClassAttr(bodyTag) {
+  // get the body tag's class attribute
+  try{
+    return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
+  }catch(e){}
+}
+
+if (rootdir) {
+
+  // go through each of the platform directories that have been prepared
+  var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
+
+  for(var x=0; x<platforms.length; x++) {
+    // open up the index.html file at the www root
+    try {
+      var platform = platforms[x].trim().toLowerCase();
+      var indexPath;
+
+      if(platform == 'android') {
+        indexPath = path.join('platforms', platform, 'assets', 'www', 'index.html');
+      } else {
+        indexPath = path.join('platforms', platform, 'www', 'index.html');
+      }
+
+      if(fs.existsSync(indexPath)) {
+        addPlatformBodyTag(indexPath, platform);
+      }
+
+    } catch(e) {
+      process.stdout.write(e);
+    }
+  }
+
+}

+ 4 - 0
ionic/ionic.project

@@ -0,0 +1,4 @@
+{
+  "name": "ionic",
+  "app_id": ""
+}

+ 21 - 0
ionic/package.json

@@ -0,0 +1,21 @@
+{
+  "name": "ionic-project",
+  "version": "1.0.0",
+  "description": "An Ionic project",
+  "dependencies": {
+    "gulp": "^3.5.6",
+    "gulp-sass": "^1.3.3",
+    "gulp-concat": "^2.2.0",
+    "gulp-minify-css": "^0.3.0",
+    "gulp-rename": "^1.2.0"
+  },
+  "devDependencies": {
+    "bower": "^1.3.3",
+    "gulp-util": "^2.2.14",
+    "shelljs": "^0.3.0"
+  },
+  "cordovaPlugins": [],
+  "cordovaPlatforms": [
+    "ios"
+  ]
+}

+ 11 - 0
ionic/plugins/ios.json

@@ -0,0 +1,11 @@
+{
+    "prepare_queue": {
+        "installed": [],
+        "uninstalled": []
+    },
+    "config_munge": {
+        "files": {}
+    },
+    "installed_plugins": {},
+    "dependent_plugins": {}
+}

BIN
ionic/resources/android/icon/drawable-hdpi-icon.png


BIN
ionic/resources/android/icon/drawable-ldpi-icon.png


BIN
ionic/resources/android/icon/drawable-mdpi-icon.png


BIN
ionic/resources/android/icon/drawable-xhdpi-icon.png


BIN
ionic/resources/android/icon/drawable-xxhdpi-icon.png


BIN
ionic/resources/android/icon/drawable-xxxhdpi-icon.png


BIN
ionic/resources/android/splash/drawable-land-hdpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-ldpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-mdpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-xhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-xxhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-land-xxxhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-hdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-ldpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-mdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-xhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-xxhdpi-screen.png


BIN
ionic/resources/android/splash/drawable-port-xxxhdpi-screen.png


BIN
ionic/resources/icon.png


BIN
ionic/resources/ios/icon/icon-40.png


BIN
ionic/resources/ios/icon/icon-40@2x.png


BIN
ionic/resources/ios/icon/icon-50.png


BIN
ionic/resources/ios/icon/icon-50@2x.png


BIN
ionic/resources/ios/icon/icon-60.png


BIN
ionic/resources/ios/icon/icon-60@2x.png


BIN
ionic/resources/ios/icon/icon-60@3x.png


BIN
ionic/resources/ios/icon/icon-72.png


BIN
ionic/resources/ios/icon/icon-72@2x.png


BIN
ionic/resources/ios/icon/icon-76.png


+ 0 - 0
ionic/resources/ios/icon/icon-76@2x.png


Some files were not shown because too many files changed in this diff