From e401c1dce917d2c4b52d668e0a1a6177bb4970ad Mon Sep 17 00:00:00 2001
From: aklefebvere <59811728+aklefebvere@users.noreply.github.com>
Date: Mon, 23 Mar 2020 20:28:16 -0400
Subject: [PATCH 1/4] Add files via upload
---
.../web-app/Pipfile.lock | 213 ++++++++++++++++++
.../web-app/app/models.py | 13 ++
.../web-app/app/routes.py | 30 +++
.../web-app/app/templates/tweets.html | 25 ++
4 files changed, 281 insertions(+)
create mode 100644 module1-web-application-development-with-flask/web-app/Pipfile.lock
create mode 100644 module1-web-application-development-with-flask/web-app/app/models.py
create mode 100644 module1-web-application-development-with-flask/web-app/app/routes.py
create mode 100644 module1-web-application-development-with-flask/web-app/app/templates/tweets.html
diff --git a/module1-web-application-development-with-flask/web-app/Pipfile.lock b/module1-web-application-development-with-flask/web-app/Pipfile.lock
new file mode 100644
index 00000000..7432f760
--- /dev/null
+++ b/module1-web-application-development-with-flask/web-app/Pipfile.lock
@@ -0,0 +1,213 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "d16f7a62bcdb62791968a3ad723c300ec916c731f220491c920e7d3e3ef55632"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "click": {
+ "hashes": [
+ "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
+ "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
+ ],
+ "version": "==7.1.1"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
+ "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
+ ],
+ "index": "pypi",
+ "version": "==1.1.1"
+ },
+ "flask-sqlalchemy": {
+ "hashes": [
+ "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327",
+ "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d"
+ ],
+ "index": "pypi",
+ "version": "==2.4.1"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
+ "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
+ ],
+ "version": "==1.1.0"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
+ "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
+ ],
+ "version": "==2.11.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
+ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
+ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
+ "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
+ "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
+ "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
+ "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
+ "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
+ "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
+ "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
+ "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
+ "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
+ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
+ "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
+ "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
+ "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
+ "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
+ "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
+ "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
+ "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
+ "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
+ "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
+ "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
+ "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
+ "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
+ "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
+ "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
+ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
+ "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
+ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
+ "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
+ "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
+ "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
+ ],
+ "version": "==1.1.1"
+ },
+ "python-dotenv": {
+ "hashes": [
+ "sha256:81822227f771e0cab235a2939f0f265954ac4763cafd806d845801c863bf372f",
+ "sha256:92b3123fb2d58a284f76cc92bfe4ee6c502c32ded73e8b051c4f6afc8b6751ed"
+ ],
+ "index": "pypi",
+ "version": "==0.12.0"
+ },
+ "sqlalchemy": {
+ "hashes": [
+ "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"
+ ],
+ "version": "==1.3.15"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
+ "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16"
+ ],
+ "version": "==1.0.0"
+ }
+ },
+ "develop": {
+ "astroid": {
+ "hashes": [
+ "sha256:71ea07f44df9568a75d0f354c49143a4575d90645e9fead6dfb52c26a85ed13a",
+ "sha256:840947ebfa8b58f318d42301cf8c0a20fd794a33b61cc4638e28e9e61ba32f42"
+ ],
+ "version": "==2.3.3"
+ },
+ "isort": {
+ "hashes": [
+ "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
+ "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
+ ],
+ "version": "==4.3.21"
+ },
+ "lazy-object-proxy": {
+ "hashes": [
+ "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
+ "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
+ "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
+ "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
+ "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
+ "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
+ "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
+ "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
+ "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
+ "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
+ "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
+ "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
+ "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
+ "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
+ "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
+ "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
+ "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
+ "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
+ "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
+ "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
+ "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
+ ],
+ "version": "==1.4.3"
+ },
+ "mccabe": {
+ "hashes": [
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+ ],
+ "version": "==0.6.1"
+ },
+ "pylint": {
+ "hashes": [
+ "sha256:3db5468ad013380e987410a8d6956226963aed94ecb5f9d3a28acca6d9ac36cd",
+ "sha256:886e6afc935ea2590b462664b161ca9a5e40168ea99e5300935f6591ad467df4"
+ ],
+ "index": "pypi",
+ "version": "==2.4.4"
+ },
+ "six": {
+ "hashes": [
+ "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
+ "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ ],
+ "version": "==1.14.0"
+ },
+ "typed-ast": {
+ "hashes": [
+ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
+ "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
+ "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
+ "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
+ "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
+ "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
+ "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
+ "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
+ "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
+ "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
+ "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
+ "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
+ "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
+ "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
+ ],
+ "markers": "implementation_name == 'cpython' and python_version < '3.8'",
+ "version": "==1.4.1"
+ },
+ "wrapt": {
+ "hashes": [
+ "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1"
+ ],
+ "version": "==1.11.2"
+ }
+ }
+}
diff --git a/module1-web-application-development-with-flask/web-app/app/models.py b/module1-web-application-development-with-flask/web-app/app/models.py
new file mode 100644
index 00000000..6cca8087
--- /dev/null
+++ b/module1-web-application-development-with-flask/web-app/app/models.py
@@ -0,0 +1,13 @@
+# Create some database models
+
+from app import db
+
+class User(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.String, nullable=False)
+ user_id = db.Column(db.Integer, nullable=False)
+
+class Tweet(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ tweet = db.Column(db.String, nullable=False)
+ user_id = db.Column(db.Integer, nullable=False)
\ No newline at end of file
diff --git a/module1-web-application-development-with-flask/web-app/app/routes.py b/module1-web-application-development-with-flask/web-app/app/routes.py
new file mode 100644
index 00000000..767f667e
--- /dev/null
+++ b/module1-web-application-development-with-flask/web-app/app/routes.py
@@ -0,0 +1,30 @@
+from flask import current_app as app
+from flask import render_template, url_for, redirect, request, flash
+from .models import User, Tweet, db
+
+@app.route('/', methods = ['GET','POST'])
+def home():
+ print("yay it worked")
+ return render_template("tweets.html")
+
+@app.route('/create_tweet', methods=["POST"])
+def create_tweet():
+ name = request.form['Name']
+ id = request.form["Id"]
+ id_exist = User.query.filter_by(user_id=id).first()
+ name_id_exist = User.query.filter_by(user_id=id, name=name).first()
+
+ if id_exist:
+ if name_id_exist:
+ new_tweet = Tweet(tweet=request.form['Tweet'], user_id=request.form["Id"])
+ db.session.add(new_tweet)
+ else:
+ flash("This name does not match the Id!")
+ else:
+ new_user = User(name=request.form['Name'], user_id=request.form["Id"])
+ new_tweet = Tweet(tweet=request.form['Tweet'], user_id=request.form["Id"])
+ db.session.add(new_user)
+ db.session.add(new_tweet)
+
+ db.session.commit()
+ return redirect('/')
\ No newline at end of file
diff --git a/module1-web-application-development-with-flask/web-app/app/templates/tweets.html b/module1-web-application-development-with-flask/web-app/app/templates/tweets.html
new file mode 100644
index 00000000..1dc1f48d
--- /dev/null
+++ b/module1-web-application-development-with-flask/web-app/app/templates/tweets.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+ Tweets
+
+
+ This is a test
+
+ {% with message = get_flashed_messages() %}
+ {% if message %}
+ {message}
+ {% endif %}
+ {% endwith %}
+
+
\ No newline at end of file
From 8c7efc8ae3581c3b341008c39054fae38550ecc9 Mon Sep 17 00:00:00 2001
From: aklefebvere <59811728+aklefebvere@users.noreply.github.com>
Date: Tue, 24 Mar 2020 20:55:30 -0400
Subject: [PATCH 2/4] Add files via upload
---
.../web-app/Pipfile.lock | 320 ++++++++++++++++++
.../web-app/app/Services/basilica_service.py | 21 ++
.../web-app/app/Services/stock_service.py | 19 ++
.../web-app/app/Services/twitter_service.py | 49 +++
.../web-app/app/models.py | 27 ++
.../web-app/app/routes.py | 90 +++++
.../web-app/app/templates/our_users.html | 16 +
.../web-app/app/templates/tweets.html | 20 ++
8 files changed, 562 insertions(+)
create mode 100644 module2-consuming-data-from-an-api/web-app/Pipfile.lock
create mode 100644 module2-consuming-data-from-an-api/web-app/app/Services/basilica_service.py
create mode 100644 module2-consuming-data-from-an-api/web-app/app/Services/stock_service.py
create mode 100644 module2-consuming-data-from-an-api/web-app/app/Services/twitter_service.py
create mode 100644 module2-consuming-data-from-an-api/web-app/app/models.py
create mode 100644 module2-consuming-data-from-an-api/web-app/app/routes.py
create mode 100644 module2-consuming-data-from-an-api/web-app/app/templates/our_users.html
create mode 100644 module2-consuming-data-from-an-api/web-app/app/templates/tweets.html
diff --git a/module2-consuming-data-from-an-api/web-app/Pipfile.lock b/module2-consuming-data-from-an-api/web-app/Pipfile.lock
new file mode 100644
index 00000000..daef59ec
--- /dev/null
+++ b/module2-consuming-data-from-an-api/web-app/Pipfile.lock
@@ -0,0 +1,320 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "74b88441425da847cfecb71a731ae8477a71ab9b1146bf5b11150b3d9eece7b3"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "basilica": {
+ "hashes": [
+ "sha256:10d111538e7fee4ece43b9a2f0f33c8b6a34dc1a061e44c035b53ac4297e3a4d"
+ ],
+ "index": "pypi",
+ "version": "==0.2.8"
+ },
+ "certifi": {
+ "hashes": [
+ "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
+ "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
+ ],
+ "version": "==2019.11.28"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
+ "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
+ ],
+ "version": "==7.1.1"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
+ "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
+ ],
+ "index": "pypi",
+ "version": "==1.1.1"
+ },
+ "flask-sqlalchemy": {
+ "hashes": [
+ "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327",
+ "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d"
+ ],
+ "index": "pypi",
+ "version": "==2.4.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
+ "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
+ ],
+ "version": "==2.9"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
+ "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
+ ],
+ "version": "==1.1.0"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
+ "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
+ ],
+ "version": "==2.11.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
+ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
+ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
+ "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
+ "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
+ "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
+ "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
+ "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
+ "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
+ "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
+ "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
+ "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
+ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
+ "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
+ "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
+ "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
+ "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
+ "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
+ "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
+ "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
+ "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
+ "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
+ "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
+ "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
+ "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
+ "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
+ "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
+ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
+ "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
+ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
+ "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
+ "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
+ "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
+ ],
+ "version": "==1.1.1"
+ },
+ "oauthlib": {
+ "hashes": [
+ "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889",
+ "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"
+ ],
+ "version": "==3.1.0"
+ },
+ "pillow": {
+ "hashes": [
+ "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be",
+ "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946",
+ "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837",
+ "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f",
+ "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00",
+ "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d",
+ "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533",
+ "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a",
+ "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358",
+ "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda",
+ "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435",
+ "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2",
+ "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313",
+ "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff",
+ "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317",
+ "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2",
+ "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614",
+ "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0",
+ "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386",
+ "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9",
+ "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636",
+ "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865"
+ ],
+ "version": "==7.0.0"
+ },
+ "pysocks": {
+ "hashes": [
+ "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299",
+ "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5",
+ "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
+ ],
+ "version": "==1.7.1"
+ },
+ "python-dotenv": {
+ "hashes": [
+ "sha256:81822227f771e0cab235a2939f0f265954ac4763cafd806d845801c863bf372f",
+ "sha256:92b3123fb2d58a284f76cc92bfe4ee6c502c32ded73e8b051c4f6afc8b6751ed"
+ ],
+ "index": "pypi",
+ "version": "==0.12.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
+ "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
+ ],
+ "index": "pypi",
+ "version": "==2.23.0"
+ },
+ "requests-oauthlib": {
+ "hashes": [
+ "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d",
+ "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"
+ ],
+ "version": "==1.3.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
+ "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ ],
+ "version": "==1.14.0"
+ },
+ "sqlalchemy": {
+ "hashes": [
+ "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"
+ ],
+ "version": "==1.3.15"
+ },
+ "tweepy": {
+ "hashes": [
+ "sha256:8abd828ba51a85a2b5bb7373715d6d3bb32d18ac624e3a4db02e4ef8ab48316b",
+ "sha256:ecc7f200c86127903017e48824efd008734814e95f3e8e9b45ce0f4120dd08db"
+ ],
+ "index": "pypi",
+ "version": "==3.8.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
+ "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
+ ],
+ "version": "==1.25.8"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
+ "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16"
+ ],
+ "version": "==1.0.0"
+ }
+ },
+ "develop": {
+ "astroid": {
+ "hashes": [
+ "sha256:71ea07f44df9568a75d0f354c49143a4575d90645e9fead6dfb52c26a85ed13a",
+ "sha256:840947ebfa8b58f318d42301cf8c0a20fd794a33b61cc4638e28e9e61ba32f42"
+ ],
+ "version": "==2.3.3"
+ },
+ "isort": {
+ "hashes": [
+ "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
+ "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
+ ],
+ "version": "==4.3.21"
+ },
+ "lazy-object-proxy": {
+ "hashes": [
+ "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
+ "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
+ "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
+ "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
+ "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
+ "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
+ "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
+ "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
+ "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
+ "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
+ "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
+ "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
+ "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
+ "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
+ "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
+ "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
+ "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
+ "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
+ "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
+ "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
+ "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
+ ],
+ "version": "==1.4.3"
+ },
+ "mccabe": {
+ "hashes": [
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+ ],
+ "version": "==0.6.1"
+ },
+ "pylint": {
+ "hashes": [
+ "sha256:3db5468ad013380e987410a8d6956226963aed94ecb5f9d3a28acca6d9ac36cd",
+ "sha256:886e6afc935ea2590b462664b161ca9a5e40168ea99e5300935f6591ad467df4"
+ ],
+ "index": "pypi",
+ "version": "==2.4.4"
+ },
+ "six": {
+ "hashes": [
+ "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
+ "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ ],
+ "version": "==1.14.0"
+ },
+ "typed-ast": {
+ "hashes": [
+ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
+ "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
+ "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
+ "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
+ "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
+ "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
+ "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
+ "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
+ "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
+ "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
+ "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
+ "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
+ "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
+ "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
+ ],
+ "markers": "implementation_name == 'cpython' and python_version < '3.8'",
+ "version": "==1.4.1"
+ },
+ "wrapt": {
+ "hashes": [
+ "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1"
+ ],
+ "version": "==1.11.2"
+ }
+ }
+}
diff --git a/module2-consuming-data-from-an-api/web-app/app/Services/basilica_service.py b/module2-consuming-data-from-an-api/web-app/app/Services/basilica_service.py
new file mode 100644
index 00000000..8872e477
--- /dev/null
+++ b/module2-consuming-data-from-an-api/web-app/app/Services/basilica_service.py
@@ -0,0 +1,21 @@
+import basilica
+import os
+from dotenv import load_dotenv
+
+load_dotenv()
+
+API_KEY = os.getenv("BASILICA_API_KEY")
+def basilica_api_client():
+ connection = basilica.Connection(API_KEY)
+ return connection
+
+if __name__ == "__main__":
+ connection = basilica.Connection(API_KEY)
+
+ sentences = ["Hello world!", "How are you?"]
+
+ print(sentences)
+
+ embeddings = connection.embed_sentences(sentences)
+
+ print(list(embeddings)) # [[0.8556405305862427, ...], ...]
\ No newline at end of file
diff --git a/module2-consuming-data-from-an-api/web-app/app/Services/stock_service.py b/module2-consuming-data-from-an-api/web-app/app/Services/stock_service.py
new file mode 100644
index 00000000..1323ea34
--- /dev/null
+++ b/module2-consuming-data-from-an-api/web-app/app/Services/stock_service.py
@@ -0,0 +1,19 @@
+import requests
+import json
+import os
+from dotenv import load_dotenv
+
+load_dotenv()
+
+API_KEY = os.getenv("ALPHAVANTAGE_API_KEY")
+
+request_url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=TSLA&apikey={API_KEY}"
+print(request_url)
+response = requests.get(request_url)
+print(type(response)) #>
+print(response.status_code) #> 200
+print(type(response.text)) #>
+parsed_response = json.loads(response.text)
+print(type(parsed_response)) #>
+latest_close = parsed_response["Time Series (Daily)"]["2020-02-25"]["4. close"]
+print("LATEST CLOSING PRICE:", latest_close)
\ No newline at end of file
diff --git a/module2-consuming-data-from-an-api/web-app/app/Services/twitter_service.py b/module2-consuming-data-from-an-api/web-app/app/Services/twitter_service.py
new file mode 100644
index 00000000..7b0121d3
--- /dev/null
+++ b/module2-consuming-data-from-an-api/web-app/app/Services/twitter_service.py
@@ -0,0 +1,49 @@
+import os
+from dotenv import load_dotenv
+import tweepy
+from pprint import pprint
+
+load_dotenv()
+
+consumer_key = os.getenv("TWITTER_API_KEY", default="OOPS")
+consumer_secret = os.getenv("TWITTER_API_SECRET", default="OOPS")
+access_token = os.getenv("TWITTER_ACCESS_TOKEN", default="OOPS")
+access_token_secret = os.getenv("TWITTER_ACCESS_TOKEN_SECRET", default="OOPS")
+
+def twitter_api_client():
+ auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
+ auth.set_access_token(access_token, access_token_secret)
+# print("AUTH", type(auth))
+ api = tweepy.API(auth)
+ return api
+# print("API", type(api)) #>
+
+#breakpoint()
+#public_tweets = api.home_timeline()
+#for tweet in public_tweets:
+# print(tweet.text)
+# get information about a twitter user:
+
+if __name__ == "__main__":
+ api = twitter_api_client()
+ screen_name = "elonmusk"
+ print("--------------")
+
+ print("USER...")
+ user = api.get_user(screen_name)
+ print(type(user)) #>
+ print(user.screen_name)
+ print(user.followers_count)
+ pprint(user._json)
+ print("--------------")
+
+ print("STATUSES...")
+ # get that user's tweets:
+ # see: http://docs.tweepy.org/en/latest/api.html#API.user_timeline
+ statuses = api.user_timeline(screen_name, tweet_mode="extended", count=150, exclude_replies=True, include_rts=False)
+
+ for status in statuses:
+ print(type(status)) #>
+ #pprint(status._json)
+ #breakpoint()
+ print(status.full_text)
\ No newline at end of file
diff --git a/module2-consuming-data-from-an-api/web-app/app/models.py b/module2-consuming-data-from-an-api/web-app/app/models.py
new file mode 100644
index 00000000..31e5a478
--- /dev/null
+++ b/module2-consuming-data-from-an-api/web-app/app/models.py
@@ -0,0 +1,27 @@
+# Create some database models
+
+from app import db
+
+class User(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.String, nullable=False)
+ user_id = db.Column(db.Integer, nullable=False)
+
+class Tweet(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ tweet = db.Column(db.String, nullable=False)
+ user_id = db.Column(db.Integer, nullable=False)
+
+class T_User(db.Model):
+ id = db.Column(db.BigInteger, primary_key=True)
+ screen_name = db.Column(db.String(128), nullable=False)
+ name = db.Column(db.String)
+ location = db.Column(db.String)
+ followers_count = db.Column(db.Integer)
+ latest_tweet_id = db.Column(db.BigInteger)
+
+class T_Tweet(db.Model):
+ id = db.Column(db.BigInteger, primary_key=True)
+ user_id = db.Column(db.BigInteger) # , db.ForeignKey("T_User.id")
+ full_text = db.Column (db.String(500))
+ embedding = db.Column(db.PickleType)
\ No newline at end of file
diff --git a/module2-consuming-data-from-an-api/web-app/app/routes.py b/module2-consuming-data-from-an-api/web-app/app/routes.py
new file mode 100644
index 00000000..c8ea5479
--- /dev/null
+++ b/module2-consuming-data-from-an-api/web-app/app/routes.py
@@ -0,0 +1,90 @@
+from flask import current_app as app
+from flask import render_template, url_for, redirect, request, flash, make_response
+from .models import User, Tweet, db, T_User, T_Tweet
+from app.Services.twitter_service import twitter_api_client
+from app.Services.basilica_service import basilica_api_client
+
+@app.route('/', methods = ['GET','POST'])
+def home():
+ print("yay it worked")
+ return render_template("tweets.html")
+
+@app.route('/create_tweet', methods=["POST"])
+def create_tweet():
+ name = request.form['Name']
+ id = request.form["Id"]
+ id_exist = User.query.filter_by(user_id=id).first()
+ name_id_exist = User.query.filter_by(user_id=id, name=name).first()
+
+ if id_exist:
+ if name_id_exist:
+ new_tweet = Tweet(tweet=request.form['Tweet'], user_id=request.form["Id"])
+ db.session.add(new_tweet)
+ else:
+ return make_response("The name does not match the Id!")
+ else:
+ new_user = User(name=request.form['Name'], user_id=request.form["Id"])
+ new_tweet = Tweet(tweet=request.form['Tweet'], user_id=request.form["Id"])
+ db.session.add(new_user)
+ db.session.add(new_tweet)
+
+ db.session.commit()
+ return redirect('/')
+
+@app.route('/display_users', methods = ['GET'])
+def display_users():
+ users = User.query.all()
+ return render_template("our_users.html", users=users)
+
+
+@app.route('/')
+def get_user(screen_name=None):
+ # Instansiate twitter api class
+ api = twitter_api_client()
+ # grab username from url and create the api.get_user object
+ twitter_user = api.get_user(screen_name)
+ # Grab all the tweets from the username in the url
+ statuses = api.user_timeline(screen_name, tweet_mode="extended", count=150, exclude_replies=True, include_rts=False)
+ # Create a Twitter Username object if one doesn't exist already in the db
+ db_user = T_User.query.get(twitter_user.id) or T_User(id=twitter_user.id)
+ # Insert twitter screen name
+ db_user.screen_name = twitter_user.screen_name
+ # Insert twitter user name
+ db_user.name = twitter_user.name
+ # Insert twitter user location
+ db_user.location = twitter_user.location
+ # Insert twitter user follower count
+ db_user.followers_count = twitter_user.followers_count
+ # Add Twitter User Object into the db
+ db.session.add(db_user)
+ # Commit the changes onto the db
+ db.session.commit()
+ # Instansiate basilica api class
+ basilica_api = basilica_api_client()
+ # List comprehension that grabs all the tweets from status and puts it into full_text format
+ all_tweets = [status.full_text for status in statuses]
+ # Creates a list of all embedding values for each tweet in alL_tweets
+ embeddings = list(basilica_api.embed_sentences(all_tweets, model="twitter"))
+ # Iterate through each status in statuses
+
+ # Create counter variable
+ counter = 0
+ for status in statuses:
+ # create user twitter tweets object from the T_Tweet class if the id doesn't already exist in the db
+ db_tweet = T_Tweet.query.get(status.id) or T_Tweet(id=status.id)
+ # inserts the twitter user id as the tweet user id
+ db_tweet.user_id = db_user.id
+ # inserts the full tweet from the twitter user
+ db_tweet.full_text = status.full_text
+ # creates a variable that holds a single embedding value from a single tweet
+ embedding = embeddings[counter]
+ # inserts the embedding value from the user's tweet
+ db_tweet.embedding = embedding
+ # Add the changes to the db
+ db.session.add(db_tweet)
+ # Increase the counter by one to iterate through each tweet from the list
+ counter+=1
+ # commit changes
+ db.session.commit()
+ # Return string if everything worked properly
+ return "User has been added to the data base!... hopefully..."
\ No newline at end of file
diff --git a/module2-consuming-data-from-an-api/web-app/app/templates/our_users.html b/module2-consuming-data-from-an-api/web-app/app/templates/our_users.html
new file mode 100644
index 00000000..fdd4b9bd
--- /dev/null
+++ b/module2-consuming-data-from-an-api/web-app/app/templates/our_users.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ {% if users %}
+ {% for user in users %}
+ {{user['name']}}
+ {% endfor %}
+ {% else %}
+ There are no users in our database
+ {% endif %}
+
+
\ No newline at end of file
diff --git a/module2-consuming-data-from-an-api/web-app/app/templates/tweets.html b/module2-consuming-data-from-an-api/web-app/app/templates/tweets.html
new file mode 100644
index 00000000..84c299c5
--- /dev/null
+++ b/module2-consuming-data-from-an-api/web-app/app/templates/tweets.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Tweets
+
+
+ This is a test
+
+
+
\ No newline at end of file
From 8dcc9763c1c9bcda9a708be6e2efa4d753ffe83a Mon Sep 17 00:00:00 2001
From: aklefebvere <59811728+aklefebvere@users.noreply.github.com>
Date: Wed, 25 Mar 2020 20:18:24 -0400
Subject: [PATCH 3/4] Add files via upload
---
.../web-app/Pipfile.lock | 406 ++++++++++++++++++
.../web-app/app/Services/basilica_service.py | 21 +
.../web-app/app/Services/stock_service.py | 19 +
.../web-app/app/Services/twitter_service.py | 49 +++
.../web-app/app/models.py | 32 ++
.../web-app/app/routes.py | 145 +++++++
.../web-app/app/templates/home.html | 21 +
.../web-app/app/templates/predict_layout.html | 20 +
.../web-app/app/templates/results.html | 16 +
.../web-app/app/templates/tweets.html | 20 +
10 files changed, 749 insertions(+)
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/Pipfile.lock
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/Services/basilica_service.py
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/Services/stock_service.py
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/Services/twitter_service.py
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/models.py
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/routes.py
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/templates/home.html
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/templates/predict_layout.html
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/templates/results.html
create mode 100644 module3-adding-data-science-to-a-web-application/web-app/app/templates/tweets.html
diff --git a/module3-adding-data-science-to-a-web-application/web-app/Pipfile.lock b/module3-adding-data-science-to-a-web-application/web-app/Pipfile.lock
new file mode 100644
index 00000000..edc8aa1a
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/Pipfile.lock
@@ -0,0 +1,406 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "6924d39ae5dd034d4b96063cff7caff19e75f19014556cc081ae9b0200be3d2b"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "basilica": {
+ "hashes": [
+ "sha256:10d111538e7fee4ece43b9a2f0f33c8b6a34dc1a061e44c035b53ac4297e3a4d"
+ ],
+ "index": "pypi",
+ "version": "==0.2.8"
+ },
+ "certifi": {
+ "hashes": [
+ "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
+ "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
+ ],
+ "version": "==2019.11.28"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
+ "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
+ ],
+ "version": "==7.1.1"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
+ "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
+ ],
+ "index": "pypi",
+ "version": "==1.1.1"
+ },
+ "flask-sqlalchemy": {
+ "hashes": [
+ "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327",
+ "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d"
+ ],
+ "index": "pypi",
+ "version": "==2.4.1"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
+ "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
+ ],
+ "version": "==2.9"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
+ "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
+ ],
+ "version": "==1.1.0"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
+ "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
+ ],
+ "version": "==2.11.1"
+ },
+ "joblib": {
+ "hashes": [
+ "sha256:0630eea4f5664c463f23fbf5dcfc54a2bc6168902719fa8e19daf033022786c8",
+ "sha256:bdb4fd9b72915ffb49fde2229ce482dd7ae79d842ed8c2b4c932441495af1403"
+ ],
+ "version": "==0.14.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
+ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
+ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
+ "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
+ "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
+ "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
+ "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
+ "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
+ "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
+ "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
+ "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
+ "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
+ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
+ "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
+ "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
+ "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
+ "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
+ "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
+ "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
+ "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
+ "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
+ "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
+ "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
+ "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
+ "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
+ "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
+ "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
+ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
+ "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
+ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
+ "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
+ "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
+ "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
+ ],
+ "version": "==1.1.1"
+ },
+ "numpy": {
+ "hashes": [
+ "sha256:1598a6de323508cfeed6b7cd6c4efb43324f4692e20d1f76e1feec7f59013448",
+ "sha256:1b0ece94018ae21163d1f651b527156e1f03943b986188dd81bc7e066eae9d1c",
+ "sha256:2e40be731ad618cb4974d5ba60d373cdf4f1b8dcbf1dcf4d9dff5e212baf69c5",
+ "sha256:4ba59db1fcc27ea31368af524dcf874d9277f21fd2e1f7f1e2e0c75ee61419ed",
+ "sha256:59ca9c6592da581a03d42cc4e270732552243dc45e87248aa8d636d53812f6a5",
+ "sha256:5e0feb76849ca3e83dd396254e47c7dba65b3fa9ed3df67c2556293ae3e16de3",
+ "sha256:6d205249a0293e62bbb3898c4c2e1ff8a22f98375a34775a259a0523111a8f6c",
+ "sha256:6fcc5a3990e269f86d388f165a089259893851437b904f422d301cdce4ff25c8",
+ "sha256:82847f2765835c8e5308f136bc34018d09b49037ec23ecc42b246424c767056b",
+ "sha256:87902e5c03355335fc5992a74ba0247a70d937f326d852fc613b7f53516c0963",
+ "sha256:9ab21d1cb156a620d3999dd92f7d1c86824c622873841d6b080ca5495fa10fef",
+ "sha256:a1baa1dc8ecd88fb2d2a651671a84b9938461e8a8eed13e2f0a812a94084d1fa",
+ "sha256:a244f7af80dacf21054386539699ce29bcc64796ed9850c99a34b41305630286",
+ "sha256:a35af656a7ba1d3decdd4fae5322b87277de8ac98b7d9da657d9e212ece76a61",
+ "sha256:b1fe1a6f3a6f355f6c29789b5927f8bd4f134a4bd9a781099a7c4f66af8850f5",
+ "sha256:b5ad0adb51b2dee7d0ee75a69e9871e2ddfb061c73ea8bc439376298141f77f5",
+ "sha256:ba3c7a2814ec8a176bb71f91478293d633c08582119e713a0c5351c0f77698da",
+ "sha256:cd77d58fb2acf57c1d1ee2835567cd70e6f1835e32090538f17f8a3a99e5e34b",
+ "sha256:cdb3a70285e8220875e4d2bc394e49b4988bdb1298ffa4e0bd81b2f613be397c",
+ "sha256:deb529c40c3f1e38d53d5ae6cd077c21f1d49e13afc7936f7f868455e16b64a0",
+ "sha256:e7894793e6e8540dbeac77c87b489e331947813511108ae097f1715c018b8f3d"
+ ],
+ "version": "==1.18.2"
+ },
+ "oauthlib": {
+ "hashes": [
+ "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889",
+ "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"
+ ],
+ "version": "==3.1.0"
+ },
+ "pillow": {
+ "hashes": [
+ "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be",
+ "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946",
+ "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837",
+ "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f",
+ "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00",
+ "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d",
+ "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533",
+ "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a",
+ "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358",
+ "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda",
+ "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435",
+ "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2",
+ "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313",
+ "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff",
+ "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317",
+ "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2",
+ "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614",
+ "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0",
+ "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386",
+ "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9",
+ "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636",
+ "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865"
+ ],
+ "version": "==7.0.0"
+ },
+ "pysocks": {
+ "hashes": [
+ "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299",
+ "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5",
+ "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
+ ],
+ "version": "==1.7.1"
+ },
+ "python-dotenv": {
+ "hashes": [
+ "sha256:81822227f771e0cab235a2939f0f265954ac4763cafd806d845801c863bf372f",
+ "sha256:92b3123fb2d58a284f76cc92bfe4ee6c502c32ded73e8b051c4f6afc8b6751ed"
+ ],
+ "index": "pypi",
+ "version": "==0.12.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
+ "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
+ ],
+ "index": "pypi",
+ "version": "==2.23.0"
+ },
+ "requests-oauthlib": {
+ "hashes": [
+ "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d",
+ "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"
+ ],
+ "version": "==1.3.0"
+ },
+ "scikit-learn": {
+ "hashes": [
+ "sha256:1bf45e62799b6938357cfce19f72e3751448c4b27010e4f98553da669b5bbd86",
+ "sha256:267ad874b54c67b479c3b45eb132ef4a56ab2b27963410624a413a4e2a3fc388",
+ "sha256:2d1bb83d6c51a81193d8a6b5f31930e2959c0e1019d49bdd03f54163735dae4b",
+ "sha256:349ba3d837fb3f7cb2b91486c43713e4b7de17f9e852f165049b1b7ac2f81478",
+ "sha256:3f4d8eea3531d3eaf613fa33f711113dfff6021d57a49c9d319af4afb46f72f0",
+ "sha256:4990f0e166292d2a0f0ee528233723bcfd238bfdb3ec2512a9e27f5695362f35",
+ "sha256:57538d138ba54407d21e27c306735cbd42a6aae0df6a5a30c7a6edde46b0017d",
+ "sha256:5b722e8bb708f254af028dc2da86d23df5371cba57e24f889b672e7b15423caa",
+ "sha256:6043e2c4ccfc68328c331b0fc19691be8fb02bd76d694704843a23ad651de902",
+ "sha256:672ea38eb59b739a8907ec063642b486bcb5a2073dda5b72b7983eeaf1fd67c1",
+ "sha256:73207dca6e70f8f611f28add185cf3a793c8232a1722f21d82259560dc35cd50",
+ "sha256:83fc104a799cb340054e485c25dfeee712b36f5638fb374eba45a9db490f16ff",
+ "sha256:8416150ab505f1813da02cdbdd9f367b05bfc75cf251235015bb09f8674358a0",
+ "sha256:84e759a766c315deb5c85139ff879edbb0aabcddb9358acf499564ed1c21e337",
+ "sha256:8ed66ab27b3d68e57bb1f315fc35e595a5c4a1f108c3420943de4d18fc40e615",
+ "sha256:a7f8aa93f61aaad080b29a9018db93ded0586692c03ddf2122e47dd1d3a14e1b",
+ "sha256:ddd3bf82977908ff69303115dd5697606e669d8a7eafd7d83bb153ef9e11bd5e",
+ "sha256:de9933297f8659ee3bb330eafdd80d74cd73d5dab39a9026b65a4156bc479063",
+ "sha256:ea91a70a992ada395efc3d510cf011dc2d99dc9037bb38cd1cb00e14745005f5",
+ "sha256:eb4c9f0019abb374a2e55150f070a333c8f990b850d1eb4dfc2765fc317ffc7c",
+ "sha256:ffce8abfdcd459e72e5b91727b247b401b22253cbd18d251f842a60e26262d6f"
+ ],
+ "index": "pypi",
+ "version": "==0.22.2.post1"
+ },
+ "scipy": {
+ "hashes": [
+ "sha256:00af72998a46c25bdb5824d2b729e7dabec0c765f9deb0b504f928591f5ff9d4",
+ "sha256:0902a620a381f101e184a958459b36d3ee50f5effd186db76e131cbefcbb96f7",
+ "sha256:1e3190466d669d658233e8a583b854f6386dd62d655539b77b3fa25bfb2abb70",
+ "sha256:2cce3f9847a1a51019e8c5b47620da93950e58ebc611f13e0d11f4980ca5fecb",
+ "sha256:3092857f36b690a321a662fe5496cb816a7f4eecd875e1d36793d92d3f884073",
+ "sha256:386086e2972ed2db17cebf88610aab7d7f6e2c0ca30042dc9a89cf18dcc363fa",
+ "sha256:71eb180f22c49066f25d6df16f8709f215723317cc951d99e54dc88020ea57be",
+ "sha256:770254a280d741dd3436919d47e35712fb081a6ff8bafc0f319382b954b77802",
+ "sha256:787cc50cab3020a865640aba3485e9fbd161d4d3b0d03a967df1a2881320512d",
+ "sha256:8a07760d5c7f3a92e440ad3aedcc98891e915ce857664282ae3c0220f3301eb6",
+ "sha256:8d3bc3993b8e4be7eade6dcc6fd59a412d96d3a33fa42b0fa45dc9e24495ede9",
+ "sha256:9508a7c628a165c2c835f2497837bf6ac80eb25291055f56c129df3c943cbaf8",
+ "sha256:a144811318853a23d32a07bc7fd5561ff0cac5da643d96ed94a4ffe967d89672",
+ "sha256:a1aae70d52d0b074d8121333bc807a485f9f1e6a69742010b33780df2e60cfe0",
+ "sha256:a2d6df9eb074af7f08866598e4ef068a2b310d98f87dc23bd1b90ec7bdcec802",
+ "sha256:bb517872058a1f087c4528e7429b4a44533a902644987e7b2fe35ecc223bc408",
+ "sha256:c5cac0c0387272ee0e789e94a570ac51deb01c796b37fb2aad1fb13f85e2f97d",
+ "sha256:cc971a82ea1170e677443108703a2ec9ff0f70752258d0e9f5433d00dda01f59",
+ "sha256:dba8306f6da99e37ea08c08fef6e274b5bf8567bb094d1dbe86a20e532aca088",
+ "sha256:dc60bb302f48acf6da8ca4444cfa17d52c63c5415302a9ee77b3b21618090521",
+ "sha256:dee1bbf3a6c8f73b6b218cb28eed8dd13347ea2f87d572ce19b289d6fd3fbc59"
+ ],
+ "version": "==1.4.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
+ "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ ],
+ "version": "==1.14.0"
+ },
+ "sqlalchemy": {
+ "hashes": [
+ "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"
+ ],
+ "version": "==1.3.15"
+ },
+ "tweepy": {
+ "hashes": [
+ "sha256:8abd828ba51a85a2b5bb7373715d6d3bb32d18ac624e3a4db02e4ef8ab48316b",
+ "sha256:ecc7f200c86127903017e48824efd008734814e95f3e8e9b45ce0f4120dd08db"
+ ],
+ "index": "pypi",
+ "version": "==3.8.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
+ "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
+ ],
+ "version": "==1.25.8"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
+ "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16"
+ ],
+ "version": "==1.0.0"
+ }
+ },
+ "develop": {
+ "astroid": {
+ "hashes": [
+ "sha256:71ea07f44df9568a75d0f354c49143a4575d90645e9fead6dfb52c26a85ed13a",
+ "sha256:840947ebfa8b58f318d42301cf8c0a20fd794a33b61cc4638e28e9e61ba32f42"
+ ],
+ "version": "==2.3.3"
+ },
+ "isort": {
+ "hashes": [
+ "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
+ "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
+ ],
+ "version": "==4.3.21"
+ },
+ "lazy-object-proxy": {
+ "hashes": [
+ "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
+ "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
+ "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
+ "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
+ "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
+ "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
+ "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
+ "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
+ "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
+ "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
+ "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
+ "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
+ "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
+ "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
+ "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
+ "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
+ "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
+ "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
+ "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
+ "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
+ "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
+ ],
+ "version": "==1.4.3"
+ },
+ "mccabe": {
+ "hashes": [
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+ ],
+ "version": "==0.6.1"
+ },
+ "pylint": {
+ "hashes": [
+ "sha256:3db5468ad013380e987410a8d6956226963aed94ecb5f9d3a28acca6d9ac36cd",
+ "sha256:886e6afc935ea2590b462664b161ca9a5e40168ea99e5300935f6591ad467df4"
+ ],
+ "index": "pypi",
+ "version": "==2.4.4"
+ },
+ "six": {
+ "hashes": [
+ "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
+ "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ ],
+ "version": "==1.14.0"
+ },
+ "typed-ast": {
+ "hashes": [
+ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
+ "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
+ "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
+ "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
+ "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
+ "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
+ "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
+ "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
+ "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
+ "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
+ "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
+ "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
+ "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
+ "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
+ ],
+ "markers": "implementation_name == 'cpython' and python_version < '3.8'",
+ "version": "==1.4.1"
+ },
+ "wrapt": {
+ "hashes": [
+ "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1"
+ ],
+ "version": "==1.11.2"
+ }
+ }
+}
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/Services/basilica_service.py b/module3-adding-data-science-to-a-web-application/web-app/app/Services/basilica_service.py
new file mode 100644
index 00000000..8872e477
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/Services/basilica_service.py
@@ -0,0 +1,21 @@
+import basilica
+import os
+from dotenv import load_dotenv
+
+load_dotenv()
+
+API_KEY = os.getenv("BASILICA_API_KEY")
+def basilica_api_client():
+ connection = basilica.Connection(API_KEY)
+ return connection
+
+if __name__ == "__main__":
+ connection = basilica.Connection(API_KEY)
+
+ sentences = ["Hello world!", "How are you?"]
+
+ print(sentences)
+
+ embeddings = connection.embed_sentences(sentences)
+
+ print(list(embeddings)) # [[0.8556405305862427, ...], ...]
\ No newline at end of file
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/Services/stock_service.py b/module3-adding-data-science-to-a-web-application/web-app/app/Services/stock_service.py
new file mode 100644
index 00000000..1323ea34
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/Services/stock_service.py
@@ -0,0 +1,19 @@
+import requests
+import json
+import os
+from dotenv import load_dotenv
+
+load_dotenv()
+
+API_KEY = os.getenv("ALPHAVANTAGE_API_KEY")
+
+request_url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=TSLA&apikey={API_KEY}"
+print(request_url)
+response = requests.get(request_url)
+print(type(response)) #>
+print(response.status_code) #> 200
+print(type(response.text)) #>
+parsed_response = json.loads(response.text)
+print(type(parsed_response)) #>
+latest_close = parsed_response["Time Series (Daily)"]["2020-02-25"]["4. close"]
+print("LATEST CLOSING PRICE:", latest_close)
\ No newline at end of file
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/Services/twitter_service.py b/module3-adding-data-science-to-a-web-application/web-app/app/Services/twitter_service.py
new file mode 100644
index 00000000..7b0121d3
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/Services/twitter_service.py
@@ -0,0 +1,49 @@
+import os
+from dotenv import load_dotenv
+import tweepy
+from pprint import pprint
+
+load_dotenv()
+
+consumer_key = os.getenv("TWITTER_API_KEY", default="OOPS")
+consumer_secret = os.getenv("TWITTER_API_SECRET", default="OOPS")
+access_token = os.getenv("TWITTER_ACCESS_TOKEN", default="OOPS")
+access_token_secret = os.getenv("TWITTER_ACCESS_TOKEN_SECRET", default="OOPS")
+
+def twitter_api_client():
+ auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
+ auth.set_access_token(access_token, access_token_secret)
+# print("AUTH", type(auth))
+ api = tweepy.API(auth)
+ return api
+# print("API", type(api)) #>
+
+#breakpoint()
+#public_tweets = api.home_timeline()
+#for tweet in public_tweets:
+# print(tweet.text)
+# get information about a twitter user:
+
+if __name__ == "__main__":
+ api = twitter_api_client()
+ screen_name = "elonmusk"
+ print("--------------")
+
+ print("USER...")
+ user = api.get_user(screen_name)
+ print(type(user)) #>
+ print(user.screen_name)
+ print(user.followers_count)
+ pprint(user._json)
+ print("--------------")
+
+ print("STATUSES...")
+ # get that user's tweets:
+ # see: http://docs.tweepy.org/en/latest/api.html#API.user_timeline
+ statuses = api.user_timeline(screen_name, tweet_mode="extended", count=150, exclude_replies=True, include_rts=False)
+
+ for status in statuses:
+ print(type(status)) #>
+ #pprint(status._json)
+ #breakpoint()
+ print(status.full_text)
\ No newline at end of file
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/models.py b/module3-adding-data-science-to-a-web-application/web-app/app/models.py
new file mode 100644
index 00000000..944dcd33
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/models.py
@@ -0,0 +1,32 @@
+# Create some database models
+
+from app import db
+
+class User(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.String, nullable=False)
+ user_id = db.Column(db.Integer, nullable=False)
+
+class Tweet(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ tweet = db.Column(db.String, nullable=False)
+ user_id = db.Column(db.Integer, nullable=False)
+
+class T_User(db.Model):
+
+ __tablename__ = "t_user"
+
+ id = db.Column(db.BigInteger, primary_key=True)
+ screen_name = db.Column(db.String(128), nullable=False)
+ name = db.Column(db.String)
+ location = db.Column(db.String)
+ followers_count = db.Column(db.Integer)
+ latest_tweet_id = db.Column(db.BigInteger)
+
+class T_Tweet(db.Model):
+ id = db.Column(db.BigInteger, primary_key=True)
+ user_id = db.Column(db.BigInteger, db.ForeignKey("t_user.id"))
+ full_text = db.Column (db.String(500))
+ embedding = db.Column(db.PickleType)
+
+ user = db.relationship("T_User", backref=db.backref("tweets", lazy=True))
\ No newline at end of file
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/routes.py b/module3-adding-data-science-to-a-web-application/web-app/app/routes.py
new file mode 100644
index 00000000..dc06e3e6
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/routes.py
@@ -0,0 +1,145 @@
+from flask import current_app as app
+from flask import render_template, url_for, redirect, request, flash, make_response
+from .models import User, Tweet, db, T_User, T_Tweet
+from app.Services.twitter_service import twitter_api_client
+from app.Services.basilica_service import basilica_api_client
+from sklearn.linear_model import LogisticRegression
+
+
+@app.route('/', methods = ['GET','POST'])
+def home():
+ users = User.query.all()
+ return render_template("home.html", users=users)
+
+@app.route('/insert_fake_user')
+def fake_user():
+ return render_template("tweets.html")
+
+@app.route('/create_tweet', methods=["POST"])
+def create_tweet():
+ name = request.form['Name']
+ id = request.form["Id"]
+ id_exist = User.query.filter_by(user_id=id).first()
+ name_id_exist = User.query.filter_by(user_id=id, name=name).first()
+
+ if id_exist:
+ if name_id_exist:
+ new_tweet = Tweet(tweet=request.form['Tweet'], user_id=request.form["Id"])
+ db.session.add(new_tweet)
+ else:
+ return make_response("The name does not match the Id!")
+ else:
+ new_user = User(name=request.form['Name'], user_id=request.form["Id"])
+ new_tweet = Tweet(tweet=request.form['Tweet'], user_id=request.form["Id"])
+ db.session.add(new_user)
+ db.session.add(new_tweet)
+
+ db.session.commit()
+ return redirect('/')
+
+@app.route('/')
+def get_user(screen_name=None):
+ # Instansiate twitter api class
+ api = twitter_api_client()
+ # grab username from url and create the api.get_user object
+ twitter_user = api.get_user(screen_name)
+ # Grab all the tweets from the username in the url
+ statuses = api.user_timeline(screen_name, tweet_mode="extended", count=500, exclude_replies=True, include_rts=False)
+ # Create a Twitter Username object if one doesn't exist already in the db
+ db_user = T_User.query.get(twitter_user.id) or T_User(id=twitter_user.id)
+ # Insert twitter screen name
+ db_user.screen_name = twitter_user.screen_name
+ # Insert twitter user name
+ db_user.name = twitter_user.name
+ # Insert twitter user location
+ db_user.location = twitter_user.location
+ # Insert twitter user follower count
+ db_user.followers_count = twitter_user.followers_count
+ # Add Twitter User Object into the db
+ db.session.add(db_user)
+ # Commit the changes onto the db
+ db.session.commit()
+ # Instansiate basilica api class
+ basilica_api = basilica_api_client()
+ # List comprehension that grabs all the tweets from status and puts it into full_text format
+ all_tweets = [status.full_text for status in statuses]
+ # Creates a list of all embedding values for each tweet in alL_tweets
+ embeddings = list(basilica_api.embed_sentences(all_tweets, model="twitter"))
+ # Create counter variable
+ counter = 0
+ # Iterate through each status in statuses
+ for status in statuses:
+ # create user twitter tweets object from the T_Tweet class if the id doesn't already exist in the db
+ db_tweet = T_Tweet.query.get(status.id) or T_Tweet(id=status.id)
+ # inserts the twitter user id as the tweet user id
+ db_tweet.user_id = db_user.id
+ # inserts the full tweet from the twitter user
+ db_tweet.full_text = status.full_text
+ # creates a variable that holds a single embedding value from a single tweet
+ embedding = embeddings[counter]
+ # inserts the embedding value from the user's tweet
+ db_tweet.embedding = embedding
+ # Add the changes to the db
+ db.session.add(db_tweet)
+ # Increase the counter by one to iterate through each tweet from the list
+ counter+=1
+ # commit changes
+ db.session.commit()
+ # Return string if everything worked properly
+ return "User has been added to the data base!... hopefully..."
+
+@app.route("/admin/db/reset")
+def reset_db():
+ print(type(db))
+ db.drop_all()
+ db.create_all()
+ return "Db has been reseted"
+
+# @app.route("/admin/db/seed")
+# def seed_db():
+# default_users = ['elonmusk', 'justinbieber', 's2t2']
+# for i in range(len(default_users)):
+# for users in default_users:
+# redirect(f'/{users}')
+# return "Done"
+
+@app.route("/predict")
+def predict_html():
+ return render_template("predict_layout.html")
+
+
+@app.route("/prediction",methods=["POST"])
+def prediction():
+ screen_name_a = request.form["User_A"]
+ screen_name_b = request.form["User_B"]
+ tweet_text = request.form["tweet"]
+
+ user_a = T_User.query.filter(T_User.screen_name == screen_name_a).one()
+ user_b = T_User.query.filter(T_User.screen_name == screen_name_b).one()
+
+ user_a_tweets = user_a.tweets
+ user_b_tweets = user_b.tweets
+
+ embeddings = []
+ labels = []
+
+ for tweet in user_a_tweets:
+ labels.append(user_a.screen_name)
+ embeddings.append(tweet.embedding)
+
+ for tweet in user_b_tweets:
+ labels.append(user_b.screen_name)
+ embeddings.append(tweet.embedding)
+
+ model = LogisticRegression(random_state=42, solver='lbfgs')
+ model.fit(embeddings, labels)
+
+ basilica_conn = basilica_api_client()
+ embed_tweet = basilica_conn.embed_sentence(tweet_text, model="twitter")
+ result = model.predict([embed_tweet])
+
+ return render_template("results.html",
+ screen_name_a=screen_name_a,
+ screen_name_b=screen_name_b,
+ tweet_text=tweet_text,
+ screen_name_most_likely=result[0])
\ No newline at end of file
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/templates/home.html b/module3-adding-data-science-to-a-web-application/web-app/app/templates/home.html
new file mode 100644
index 00000000..054c823d
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/templates/home.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+ Twitter app thingy
+ Create a fake Twitter User
+ Current fake users in database:
+ {% if users %}
+ {% for user in users %}
+ {{user['name']}}
+ {% endfor %}
+ {% else %}
+ There are no users in our database
+ {% endif %}
+ Predict which user will predict given tweet
+
+
\ No newline at end of file
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/templates/predict_layout.html b/module3-adding-data-science-to-a-web-application/web-app/app/templates/predict_layout.html
new file mode 100644
index 00000000..442b5bc7
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/templates/predict_layout.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+ Predict which user will predict given tweet
+
+
+
\ No newline at end of file
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/templates/results.html b/module3-adding-data-science-to-a-web-application/web-app/app/templates/results.html
new file mode 100644
index 00000000..7a8860c1
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/templates/results.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+ Results!
+
+ Betwween '@{{screen_name_a}}' and '@{{screen_name_b}}',
+ The user who would most likely to say '{{tweet_text}}'
+ is '@{{screen_name_most_likely}}'
+
+
+
\ No newline at end of file
diff --git a/module3-adding-data-science-to-a-web-application/web-app/app/templates/tweets.html b/module3-adding-data-science-to-a-web-application/web-app/app/templates/tweets.html
new file mode 100644
index 00000000..b9e82d6d
--- /dev/null
+++ b/module3-adding-data-science-to-a-web-application/web-app/app/templates/tweets.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Tweets
+
+
+ Create a fake twitter user that will be added into the database
+
+
+
\ No newline at end of file
From 990c2d51bcb008b952bdd4f400e6658caddabbf3 Mon Sep 17 00:00:00 2001
From: aklefebvere
Date: Thu, 26 Mar 2020 15:50:01 -0400
Subject: [PATCH 4/4] added working app to push to Heroku
---
.../web-app/.vscode/settings.json | 3 +
.../web-app/Pipfile | 21 +
.../web-app/Pipfile.lock | 452 ++++++++++++++++++
.../web-app/Procfile | 0
.../web-app/app/Services/basilica_service.py | 21 +
.../web-app/app/Services/stock_service.py | 19 +
.../web-app/app/Services/twitter_service.py | 49 ++
.../web-app/app/__init__.py | 20 +
.../web-app/app/forms.py | 0
.../web-app/app/models.py | 32 ++
.../web-app/app/routes.py | 145 ++++++
.../web-app/app/templates/home.html | 13 +
.../web-app/app/templates/predict_layout.html | 21 +
.../web-app/app/templates/results.html | 17 +
.../web-app/app/templates/tweets.html | 29 ++
.../web-app/app/test_db.sqlite | Bin 0 -> 888832 bytes
.../web-app/config.py | 12 +
.../web-app/run.py | 7 +
18 files changed, 861 insertions(+)
create mode 100644 module4-web-application-deployment/web-app/.vscode/settings.json
create mode 100644 module4-web-application-deployment/web-app/Pipfile
create mode 100644 module4-web-application-deployment/web-app/Pipfile.lock
create mode 100644 module4-web-application-deployment/web-app/Procfile
create mode 100644 module4-web-application-deployment/web-app/app/Services/basilica_service.py
create mode 100644 module4-web-application-deployment/web-app/app/Services/stock_service.py
create mode 100644 module4-web-application-deployment/web-app/app/Services/twitter_service.py
create mode 100644 module4-web-application-deployment/web-app/app/__init__.py
create mode 100644 module4-web-application-deployment/web-app/app/forms.py
create mode 100644 module4-web-application-deployment/web-app/app/models.py
create mode 100644 module4-web-application-deployment/web-app/app/routes.py
create mode 100644 module4-web-application-deployment/web-app/app/templates/home.html
create mode 100644 module4-web-application-deployment/web-app/app/templates/predict_layout.html
create mode 100644 module4-web-application-deployment/web-app/app/templates/results.html
create mode 100644 module4-web-application-deployment/web-app/app/templates/tweets.html
create mode 100644 module4-web-application-deployment/web-app/app/test_db.sqlite
create mode 100644 module4-web-application-deployment/web-app/config.py
create mode 100644 module4-web-application-deployment/web-app/run.py
diff --git a/module4-web-application-deployment/web-app/.vscode/settings.json b/module4-web-application-deployment/web-app/.vscode/settings.json
new file mode 100644
index 00000000..abc223ea
--- /dev/null
+++ b/module4-web-application-deployment/web-app/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "python.pythonPath": "/home/adriann/.local/share/virtualenvs/web-app-4nemaXEP/bin/python"
+}
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/Pipfile b/module4-web-application-deployment/web-app/Pipfile
new file mode 100644
index 00000000..f6902931
--- /dev/null
+++ b/module4-web-application-deployment/web-app/Pipfile
@@ -0,0 +1,21 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+pylint = "*"
+
+[packages]
+flask = "*"
+flask-sqlalchemy = "*"
+python-dotenv = "*"
+requests = "*"
+basilica = "*"
+tweepy = "*"
+scikit-learn = "*"
+gunicorn = "*"
+psycopg2-binary = "*"
+
+[requires]
+python_version = "3.7"
diff --git a/module4-web-application-deployment/web-app/Pipfile.lock b/module4-web-application-deployment/web-app/Pipfile.lock
new file mode 100644
index 00000000..c9267430
--- /dev/null
+++ b/module4-web-application-deployment/web-app/Pipfile.lock
@@ -0,0 +1,452 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "955cd8129a588e1bdd953d42d7eee84e70e176cfa285d3c436c54e79e1d84c8b"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "basilica": {
+ "hashes": [
+ "sha256:10d111538e7fee4ece43b9a2f0f33c8b6a34dc1a061e44c035b53ac4297e3a4d"
+ ],
+ "index": "pypi",
+ "version": "==0.2.8"
+ },
+ "certifi": {
+ "hashes": [
+ "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
+ "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
+ ],
+ "version": "==2019.11.28"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "click": {
+ "hashes": [
+ "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
+ "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
+ ],
+ "version": "==7.1.1"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
+ "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
+ ],
+ "index": "pypi",
+ "version": "==1.1.1"
+ },
+ "flask-sqlalchemy": {
+ "hashes": [
+ "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327",
+ "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d"
+ ],
+ "index": "pypi",
+ "version": "==2.4.1"
+ },
+ "gunicorn": {
+ "hashes": [
+ "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626",
+ "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"
+ ],
+ "index": "pypi",
+ "version": "==20.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
+ "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
+ ],
+ "version": "==2.9"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
+ "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
+ ],
+ "version": "==1.1.0"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
+ "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
+ ],
+ "version": "==2.11.1"
+ },
+ "joblib": {
+ "hashes": [
+ "sha256:0630eea4f5664c463f23fbf5dcfc54a2bc6168902719fa8e19daf033022786c8",
+ "sha256:bdb4fd9b72915ffb49fde2229ce482dd7ae79d842ed8c2b4c932441495af1403"
+ ],
+ "version": "==0.14.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
+ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
+ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
+ "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
+ "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
+ "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
+ "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
+ "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
+ "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
+ "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
+ "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
+ "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
+ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
+ "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
+ "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
+ "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
+ "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
+ "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
+ "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
+ "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
+ "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
+ "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
+ "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
+ "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
+ "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
+ "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
+ "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
+ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
+ "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
+ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
+ "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
+ "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
+ "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
+ ],
+ "version": "==1.1.1"
+ },
+ "numpy": {
+ "hashes": [
+ "sha256:1598a6de323508cfeed6b7cd6c4efb43324f4692e20d1f76e1feec7f59013448",
+ "sha256:1b0ece94018ae21163d1f651b527156e1f03943b986188dd81bc7e066eae9d1c",
+ "sha256:2e40be731ad618cb4974d5ba60d373cdf4f1b8dcbf1dcf4d9dff5e212baf69c5",
+ "sha256:4ba59db1fcc27ea31368af524dcf874d9277f21fd2e1f7f1e2e0c75ee61419ed",
+ "sha256:59ca9c6592da581a03d42cc4e270732552243dc45e87248aa8d636d53812f6a5",
+ "sha256:5e0feb76849ca3e83dd396254e47c7dba65b3fa9ed3df67c2556293ae3e16de3",
+ "sha256:6d205249a0293e62bbb3898c4c2e1ff8a22f98375a34775a259a0523111a8f6c",
+ "sha256:6fcc5a3990e269f86d388f165a089259893851437b904f422d301cdce4ff25c8",
+ "sha256:82847f2765835c8e5308f136bc34018d09b49037ec23ecc42b246424c767056b",
+ "sha256:87902e5c03355335fc5992a74ba0247a70d937f326d852fc613b7f53516c0963",
+ "sha256:9ab21d1cb156a620d3999dd92f7d1c86824c622873841d6b080ca5495fa10fef",
+ "sha256:a1baa1dc8ecd88fb2d2a651671a84b9938461e8a8eed13e2f0a812a94084d1fa",
+ "sha256:a244f7af80dacf21054386539699ce29bcc64796ed9850c99a34b41305630286",
+ "sha256:a35af656a7ba1d3decdd4fae5322b87277de8ac98b7d9da657d9e212ece76a61",
+ "sha256:b1fe1a6f3a6f355f6c29789b5927f8bd4f134a4bd9a781099a7c4f66af8850f5",
+ "sha256:b5ad0adb51b2dee7d0ee75a69e9871e2ddfb061c73ea8bc439376298141f77f5",
+ "sha256:ba3c7a2814ec8a176bb71f91478293d633c08582119e713a0c5351c0f77698da",
+ "sha256:cd77d58fb2acf57c1d1ee2835567cd70e6f1835e32090538f17f8a3a99e5e34b",
+ "sha256:cdb3a70285e8220875e4d2bc394e49b4988bdb1298ffa4e0bd81b2f613be397c",
+ "sha256:deb529c40c3f1e38d53d5ae6cd077c21f1d49e13afc7936f7f868455e16b64a0",
+ "sha256:e7894793e6e8540dbeac77c87b489e331947813511108ae097f1715c018b8f3d"
+ ],
+ "version": "==1.18.2"
+ },
+ "oauthlib": {
+ "hashes": [
+ "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889",
+ "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"
+ ],
+ "version": "==3.1.0"
+ },
+ "pillow": {
+ "hashes": [
+ "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be",
+ "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946",
+ "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837",
+ "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f",
+ "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00",
+ "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d",
+ "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533",
+ "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a",
+ "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358",
+ "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda",
+ "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435",
+ "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2",
+ "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313",
+ "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff",
+ "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317",
+ "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2",
+ "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614",
+ "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0",
+ "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386",
+ "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9",
+ "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636",
+ "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865"
+ ],
+ "version": "==7.0.0"
+ },
+ "psycopg2-binary": {
+ "hashes": [
+ "sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29",
+ "sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03",
+ "sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039",
+ "sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881",
+ "sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309",
+ "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed",
+ "sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b",
+ "sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3",
+ "sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7",
+ "sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b",
+ "sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03",
+ "sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103",
+ "sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d",
+ "sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35",
+ "sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b",
+ "sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49",
+ "sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70",
+ "sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e",
+ "sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e",
+ "sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e",
+ "sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103",
+ "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6",
+ "sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1",
+ "sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9",
+ "sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e",
+ "sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f",
+ "sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd",
+ "sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8",
+ "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f",
+ "sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4",
+ "sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964",
+ "sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"
+ ],
+ "index": "pypi",
+ "version": "==2.8.4"
+ },
+ "pysocks": {
+ "hashes": [
+ "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299",
+ "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5",
+ "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
+ ],
+ "version": "==1.7.1"
+ },
+ "python-dotenv": {
+ "hashes": [
+ "sha256:81822227f771e0cab235a2939f0f265954ac4763cafd806d845801c863bf372f",
+ "sha256:92b3123fb2d58a284f76cc92bfe4ee6c502c32ded73e8b051c4f6afc8b6751ed"
+ ],
+ "index": "pypi",
+ "version": "==0.12.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
+ "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
+ ],
+ "index": "pypi",
+ "version": "==2.23.0"
+ },
+ "requests-oauthlib": {
+ "hashes": [
+ "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d",
+ "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"
+ ],
+ "version": "==1.3.0"
+ },
+ "scikit-learn": {
+ "hashes": [
+ "sha256:1bf45e62799b6938357cfce19f72e3751448c4b27010e4f98553da669b5bbd86",
+ "sha256:267ad874b54c67b479c3b45eb132ef4a56ab2b27963410624a413a4e2a3fc388",
+ "sha256:2d1bb83d6c51a81193d8a6b5f31930e2959c0e1019d49bdd03f54163735dae4b",
+ "sha256:349ba3d837fb3f7cb2b91486c43713e4b7de17f9e852f165049b1b7ac2f81478",
+ "sha256:3f4d8eea3531d3eaf613fa33f711113dfff6021d57a49c9d319af4afb46f72f0",
+ "sha256:4990f0e166292d2a0f0ee528233723bcfd238bfdb3ec2512a9e27f5695362f35",
+ "sha256:57538d138ba54407d21e27c306735cbd42a6aae0df6a5a30c7a6edde46b0017d",
+ "sha256:5b722e8bb708f254af028dc2da86d23df5371cba57e24f889b672e7b15423caa",
+ "sha256:6043e2c4ccfc68328c331b0fc19691be8fb02bd76d694704843a23ad651de902",
+ "sha256:672ea38eb59b739a8907ec063642b486bcb5a2073dda5b72b7983eeaf1fd67c1",
+ "sha256:73207dca6e70f8f611f28add185cf3a793c8232a1722f21d82259560dc35cd50",
+ "sha256:83fc104a799cb340054e485c25dfeee712b36f5638fb374eba45a9db490f16ff",
+ "sha256:8416150ab505f1813da02cdbdd9f367b05bfc75cf251235015bb09f8674358a0",
+ "sha256:84e759a766c315deb5c85139ff879edbb0aabcddb9358acf499564ed1c21e337",
+ "sha256:8ed66ab27b3d68e57bb1f315fc35e595a5c4a1f108c3420943de4d18fc40e615",
+ "sha256:a7f8aa93f61aaad080b29a9018db93ded0586692c03ddf2122e47dd1d3a14e1b",
+ "sha256:ddd3bf82977908ff69303115dd5697606e669d8a7eafd7d83bb153ef9e11bd5e",
+ "sha256:de9933297f8659ee3bb330eafdd80d74cd73d5dab39a9026b65a4156bc479063",
+ "sha256:ea91a70a992ada395efc3d510cf011dc2d99dc9037bb38cd1cb00e14745005f5",
+ "sha256:eb4c9f0019abb374a2e55150f070a333c8f990b850d1eb4dfc2765fc317ffc7c",
+ "sha256:ffce8abfdcd459e72e5b91727b247b401b22253cbd18d251f842a60e26262d6f"
+ ],
+ "index": "pypi",
+ "version": "==0.22.2.post1"
+ },
+ "scipy": {
+ "hashes": [
+ "sha256:00af72998a46c25bdb5824d2b729e7dabec0c765f9deb0b504f928591f5ff9d4",
+ "sha256:0902a620a381f101e184a958459b36d3ee50f5effd186db76e131cbefcbb96f7",
+ "sha256:1e3190466d669d658233e8a583b854f6386dd62d655539b77b3fa25bfb2abb70",
+ "sha256:2cce3f9847a1a51019e8c5b47620da93950e58ebc611f13e0d11f4980ca5fecb",
+ "sha256:3092857f36b690a321a662fe5496cb816a7f4eecd875e1d36793d92d3f884073",
+ "sha256:386086e2972ed2db17cebf88610aab7d7f6e2c0ca30042dc9a89cf18dcc363fa",
+ "sha256:71eb180f22c49066f25d6df16f8709f215723317cc951d99e54dc88020ea57be",
+ "sha256:770254a280d741dd3436919d47e35712fb081a6ff8bafc0f319382b954b77802",
+ "sha256:787cc50cab3020a865640aba3485e9fbd161d4d3b0d03a967df1a2881320512d",
+ "sha256:8a07760d5c7f3a92e440ad3aedcc98891e915ce857664282ae3c0220f3301eb6",
+ "sha256:8d3bc3993b8e4be7eade6dcc6fd59a412d96d3a33fa42b0fa45dc9e24495ede9",
+ "sha256:9508a7c628a165c2c835f2497837bf6ac80eb25291055f56c129df3c943cbaf8",
+ "sha256:a144811318853a23d32a07bc7fd5561ff0cac5da643d96ed94a4ffe967d89672",
+ "sha256:a1aae70d52d0b074d8121333bc807a485f9f1e6a69742010b33780df2e60cfe0",
+ "sha256:a2d6df9eb074af7f08866598e4ef068a2b310d98f87dc23bd1b90ec7bdcec802",
+ "sha256:bb517872058a1f087c4528e7429b4a44533a902644987e7b2fe35ecc223bc408",
+ "sha256:c5cac0c0387272ee0e789e94a570ac51deb01c796b37fb2aad1fb13f85e2f97d",
+ "sha256:cc971a82ea1170e677443108703a2ec9ff0f70752258d0e9f5433d00dda01f59",
+ "sha256:dba8306f6da99e37ea08c08fef6e274b5bf8567bb094d1dbe86a20e532aca088",
+ "sha256:dc60bb302f48acf6da8ca4444cfa17d52c63c5415302a9ee77b3b21618090521",
+ "sha256:dee1bbf3a6c8f73b6b218cb28eed8dd13347ea2f87d572ce19b289d6fd3fbc59"
+ ],
+ "version": "==1.4.1"
+ },
+ "six": {
+ "hashes": [
+ "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
+ "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ ],
+ "version": "==1.14.0"
+ },
+ "sqlalchemy": {
+ "hashes": [
+ "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"
+ ],
+ "version": "==1.3.15"
+ },
+ "tweepy": {
+ "hashes": [
+ "sha256:8abd828ba51a85a2b5bb7373715d6d3bb32d18ac624e3a4db02e4ef8ab48316b",
+ "sha256:ecc7f200c86127903017e48824efd008734814e95f3e8e9b45ce0f4120dd08db"
+ ],
+ "index": "pypi",
+ "version": "==3.8.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
+ "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
+ ],
+ "version": "==1.25.8"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
+ "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16"
+ ],
+ "version": "==1.0.0"
+ }
+ },
+ "develop": {
+ "astroid": {
+ "hashes": [
+ "sha256:71ea07f44df9568a75d0f354c49143a4575d90645e9fead6dfb52c26a85ed13a",
+ "sha256:840947ebfa8b58f318d42301cf8c0a20fd794a33b61cc4638e28e9e61ba32f42"
+ ],
+ "version": "==2.3.3"
+ },
+ "isort": {
+ "hashes": [
+ "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
+ "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
+ ],
+ "version": "==4.3.21"
+ },
+ "lazy-object-proxy": {
+ "hashes": [
+ "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
+ "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
+ "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
+ "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
+ "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
+ "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
+ "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
+ "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
+ "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
+ "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
+ "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
+ "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
+ "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
+ "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
+ "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
+ "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
+ "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
+ "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
+ "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
+ "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
+ "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
+ ],
+ "version": "==1.4.3"
+ },
+ "mccabe": {
+ "hashes": [
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+ ],
+ "version": "==0.6.1"
+ },
+ "pylint": {
+ "hashes": [
+ "sha256:3db5468ad013380e987410a8d6956226963aed94ecb5f9d3a28acca6d9ac36cd",
+ "sha256:886e6afc935ea2590b462664b161ca9a5e40168ea99e5300935f6591ad467df4"
+ ],
+ "index": "pypi",
+ "version": "==2.4.4"
+ },
+ "six": {
+ "hashes": [
+ "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
+ "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+ ],
+ "version": "==1.14.0"
+ },
+ "typed-ast": {
+ "hashes": [
+ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
+ "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
+ "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
+ "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
+ "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
+ "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
+ "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
+ "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
+ "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
+ "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
+ "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
+ "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
+ "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
+ "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
+ ],
+ "markers": "implementation_name == 'cpython' and python_version < '3.8'",
+ "version": "==1.4.1"
+ },
+ "wrapt": {
+ "hashes": [
+ "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1"
+ ],
+ "version": "==1.11.2"
+ }
+ }
+}
diff --git a/module4-web-application-deployment/web-app/Procfile b/module4-web-application-deployment/web-app/Procfile
new file mode 100644
index 00000000..e69de29b
diff --git a/module4-web-application-deployment/web-app/app/Services/basilica_service.py b/module4-web-application-deployment/web-app/app/Services/basilica_service.py
new file mode 100644
index 00000000..8872e477
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/Services/basilica_service.py
@@ -0,0 +1,21 @@
+import basilica
+import os
+from dotenv import load_dotenv
+
+load_dotenv()
+
+API_KEY = os.getenv("BASILICA_API_KEY")
+def basilica_api_client():
+ connection = basilica.Connection(API_KEY)
+ return connection
+
+if __name__ == "__main__":
+ connection = basilica.Connection(API_KEY)
+
+ sentences = ["Hello world!", "How are you?"]
+
+ print(sentences)
+
+ embeddings = connection.embed_sentences(sentences)
+
+ print(list(embeddings)) # [[0.8556405305862427, ...], ...]
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/Services/stock_service.py b/module4-web-application-deployment/web-app/app/Services/stock_service.py
new file mode 100644
index 00000000..1323ea34
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/Services/stock_service.py
@@ -0,0 +1,19 @@
+import requests
+import json
+import os
+from dotenv import load_dotenv
+
+load_dotenv()
+
+API_KEY = os.getenv("ALPHAVANTAGE_API_KEY")
+
+request_url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=TSLA&apikey={API_KEY}"
+print(request_url)
+response = requests.get(request_url)
+print(type(response)) #>
+print(response.status_code) #> 200
+print(type(response.text)) #>
+parsed_response = json.loads(response.text)
+print(type(parsed_response)) #>
+latest_close = parsed_response["Time Series (Daily)"]["2020-02-25"]["4. close"]
+print("LATEST CLOSING PRICE:", latest_close)
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/Services/twitter_service.py b/module4-web-application-deployment/web-app/app/Services/twitter_service.py
new file mode 100644
index 00000000..7b0121d3
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/Services/twitter_service.py
@@ -0,0 +1,49 @@
+import os
+from dotenv import load_dotenv
+import tweepy
+from pprint import pprint
+
+load_dotenv()
+
+consumer_key = os.getenv("TWITTER_API_KEY", default="OOPS")
+consumer_secret = os.getenv("TWITTER_API_SECRET", default="OOPS")
+access_token = os.getenv("TWITTER_ACCESS_TOKEN", default="OOPS")
+access_token_secret = os.getenv("TWITTER_ACCESS_TOKEN_SECRET", default="OOPS")
+
+def twitter_api_client():
+ auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
+ auth.set_access_token(access_token, access_token_secret)
+# print("AUTH", type(auth))
+ api = tweepy.API(auth)
+ return api
+# print("API", type(api)) #>
+
+#breakpoint()
+#public_tweets = api.home_timeline()
+#for tweet in public_tweets:
+# print(tweet.text)
+# get information about a twitter user:
+
+if __name__ == "__main__":
+ api = twitter_api_client()
+ screen_name = "elonmusk"
+ print("--------------")
+
+ print("USER...")
+ user = api.get_user(screen_name)
+ print(type(user)) #>
+ print(user.screen_name)
+ print(user.followers_count)
+ pprint(user._json)
+ print("--------------")
+
+ print("STATUSES...")
+ # get that user's tweets:
+ # see: http://docs.tweepy.org/en/latest/api.html#API.user_timeline
+ statuses = api.user_timeline(screen_name, tweet_mode="extended", count=150, exclude_replies=True, include_rts=False)
+
+ for status in statuses:
+ print(type(status)) #>
+ #pprint(status._json)
+ #breakpoint()
+ print(status.full_text)
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/__init__.py b/module4-web-application-deployment/web-app/app/__init__.py
new file mode 100644
index 00000000..130d06c0
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/__init__.py
@@ -0,0 +1,20 @@
+from flask import Flask
+from flask_sqlalchemy import SQLAlchemy
+
+
+db = SQLAlchemy()
+
+
+def create_app():
+ app = Flask(__name__, instance_relative_config=False)
+ app.config.from_object("config.Config")
+ db.init_app(app)
+
+ with app.app_context():
+
+ # import our routes
+ from . import routes
+
+ db.create_all()
+
+ return app
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/forms.py b/module4-web-application-deployment/web-app/app/forms.py
new file mode 100644
index 00000000..e69de29b
diff --git a/module4-web-application-deployment/web-app/app/models.py b/module4-web-application-deployment/web-app/app/models.py
new file mode 100644
index 00000000..944dcd33
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/models.py
@@ -0,0 +1,32 @@
+# Create some database models
+
+from app import db
+
+class User(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.String, nullable=False)
+ user_id = db.Column(db.Integer, nullable=False)
+
+class Tweet(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ tweet = db.Column(db.String, nullable=False)
+ user_id = db.Column(db.Integer, nullable=False)
+
+class T_User(db.Model):
+
+ __tablename__ = "t_user"
+
+ id = db.Column(db.BigInteger, primary_key=True)
+ screen_name = db.Column(db.String(128), nullable=False)
+ name = db.Column(db.String)
+ location = db.Column(db.String)
+ followers_count = db.Column(db.Integer)
+ latest_tweet_id = db.Column(db.BigInteger)
+
+class T_Tweet(db.Model):
+ id = db.Column(db.BigInteger, primary_key=True)
+ user_id = db.Column(db.BigInteger, db.ForeignKey("t_user.id"))
+ full_text = db.Column (db.String(500))
+ embedding = db.Column(db.PickleType)
+
+ user = db.relationship("T_User", backref=db.backref("tweets", lazy=True))
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/routes.py b/module4-web-application-deployment/web-app/app/routes.py
new file mode 100644
index 00000000..138bf2e0
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/routes.py
@@ -0,0 +1,145 @@
+from flask import current_app as app
+from flask import render_template, url_for, redirect, request, flash, make_response
+from .models import User, Tweet, db, T_User, T_Tweet
+from app.Services.twitter_service import twitter_api_client
+from app.Services.basilica_service import basilica_api_client
+from sklearn.linear_model import LogisticRegression
+
+
+@app.route('/', methods = ['GET','POST'])
+def home():
+ return render_template("home.html")
+
+@app.route('/insert_fake_user')
+def fake_user():
+ users = User.query.all()
+ return render_template("tweets.html", users=users)
+
+@app.route('/create_tweet', methods=["POST"])
+def create_tweet():
+ name = request.form['Name']
+ id = request.form["Id"]
+ id_exist = User.query.filter_by(user_id=id).first()
+ name_id_exist = User.query.filter_by(user_id=id, name=name).first()
+
+ if id_exist:
+ if name_id_exist:
+ new_tweet = Tweet(tweet=request.form['Tweet'], user_id=request.form["Id"])
+ db.session.add(new_tweet)
+ else:
+ return make_response("The name does not match the Id!")
+ else:
+ new_user = User(name=request.form['Name'], user_id=request.form["Id"])
+ new_tweet = Tweet(tweet=request.form['Tweet'], user_id=request.form["Id"])
+ db.session.add(new_user)
+ db.session.add(new_tweet)
+
+ db.session.commit()
+ return redirect('/')
+
+@app.route('/')
+def get_user(screen_name=None):
+ # Instansiate twitter api class
+ api = twitter_api_client()
+ # grab username from url and create the api.get_user object
+ twitter_user = api.get_user(screen_name)
+ # Grab all the tweets from the username in the url
+ statuses = api.user_timeline(screen_name, tweet_mode="extended", count=500, exclude_replies=True, include_rts=False)
+ # Create a Twitter Username object if one doesn't exist already in the db
+ db_user = T_User.query.get(twitter_user.id) or T_User(id=twitter_user.id)
+ # Insert twitter screen name
+ db_user.screen_name = twitter_user.screen_name
+ # Insert twitter user name
+ db_user.name = twitter_user.name
+ # Insert twitter user location
+ db_user.location = twitter_user.location
+ # Insert twitter user follower count
+ db_user.followers_count = twitter_user.followers_count
+ # Add Twitter User Object into the db
+ db.session.add(db_user)
+ # Commit the changes onto the db
+ db.session.commit()
+ # Instansiate basilica api class
+ basilica_api = basilica_api_client()
+ # List comprehension that grabs all the tweets from status and puts it into full_text format
+ all_tweets = [status.full_text for status in statuses]
+ # Creates a list of all embedding values for each tweet in alL_tweets
+ embeddings = list(basilica_api.embed_sentences(all_tweets, model="twitter"))
+ # Create counter variable
+ counter = 0
+ # Iterate through each status in statuses
+ for status in statuses:
+ # create user twitter tweets object from the T_Tweet class if the id doesn't already exist in the db
+ db_tweet = T_Tweet.query.get(status.id) or T_Tweet(id=status.id)
+ # inserts the twitter user id as the tweet user id
+ db_tweet.user_id = db_user.id
+ # inserts the full tweet from the twitter user
+ db_tweet.full_text = status.full_text
+ # creates a variable that holds a single embedding value from a single tweet
+ embedding = embeddings[counter]
+ # inserts the embedding value from the user's tweet
+ db_tweet.embedding = embedding
+ # Add the changes to the db
+ db.session.add(db_tweet)
+ # Increase the counter by one to iterate through each tweet from the list
+ counter+=1
+ # commit changes
+ db.session.commit()
+ # Return string if everything worked properly
+ return "User has been added to the data base!... hopefully..."
+
+@app.route("/admin/db/reset")
+def reset_db():
+ print(type(db))
+ db.drop_all()
+ db.create_all()
+ return "Db has been reseted"
+
+# @app.route("/admin/db/seed")
+# def seed_db():
+# default_users = ['elonmusk', 'justinbieber', 's2t2']
+# for i in range(len(default_users)):
+# for users in default_users:
+# redirect(f'/{users}')
+# return "Done"
+
+@app.route("/predict")
+def predict_html():
+ return render_template("predict_layout.html")
+
+
+@app.route("/prediction",methods=["POST"])
+def prediction():
+ screen_name_a = request.form["User_A"]
+ screen_name_b = request.form["User_B"]
+ tweet_text = request.form["tweet"]
+
+ user_a = T_User.query.filter(T_User.screen_name == screen_name_a).one()
+ user_b = T_User.query.filter(T_User.screen_name == screen_name_b).one()
+
+ user_a_tweets = user_a.tweets
+ user_b_tweets = user_b.tweets
+
+ embeddings = []
+ labels = []
+
+ for tweet in user_a_tweets:
+ labels.append(user_a.screen_name)
+ embeddings.append(tweet.embedding)
+
+ for tweet in user_b_tweets:
+ labels.append(user_b.screen_name)
+ embeddings.append(tweet.embedding)
+
+ model = LogisticRegression(random_state=42, solver='lbfgs')
+ model.fit(embeddings, labels)
+
+ basilica_conn = basilica_api_client()
+ embed_tweet = basilica_conn.embed_sentence(tweet_text, model="twitter")
+ result = model.predict([embed_tweet])
+
+ return render_template("results.html",
+ screen_name_a=screen_name_a,
+ screen_name_b=screen_name_b,
+ tweet_text=tweet_text,
+ screen_name_most_likely=result[0])
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/templates/home.html b/module4-web-application-deployment/web-app/app/templates/home.html
new file mode 100644
index 00000000..3b58eef2
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/templates/home.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+ Twitter app thingy
+ Create a fake Twitter User
+ Predict which user will predict given tweet
+
+
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/templates/predict_layout.html b/module4-web-application-deployment/web-app/app/templates/predict_layout.html
new file mode 100644
index 00000000..574f8cd0
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/templates/predict_layout.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+ Predict which user will predict given tweet
+
+
+
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/templates/results.html b/module4-web-application-deployment/web-app/app/templates/results.html
new file mode 100644
index 00000000..4adb8f65
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/templates/results.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ Results!
+
+ Betwween '@{{screen_name_a}}' and '@{{screen_name_b}}',
+ The user who would most likely to say '{{tweet_text}}'
+ is '@{{screen_name_most_likely}}'
+
+ Return Home
+
+
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/templates/tweets.html b/module4-web-application-deployment/web-app/app/templates/tweets.html
new file mode 100644
index 00000000..cd9ba29f
--- /dev/null
+++ b/module4-web-application-deployment/web-app/app/templates/tweets.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+ Tweets
+
+
+ Create a fake twitter user that will be added into the database
+
+ Current fake users in database:
+ {% if users %}
+ {% for user in users %}
+ {{user['name']}}
+ {% endfor %}
+ {% else %}
+ There are no users in the database
+ {% endif %}
+ Return Home
+
+
\ No newline at end of file
diff --git a/module4-web-application-deployment/web-app/app/test_db.sqlite b/module4-web-application-deployment/web-app/app/test_db.sqlite
new file mode 100644
index 0000000000000000000000000000000000000000..a2ead22932b3a55d8857fe24d3d973376657e90e
GIT binary patch
literal 888832
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