-
-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Add NLP techniques and GUI to Social Media Analyzer #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,3 @@ | ||
| requests | ||
| nltk | ||
| textblob |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import unittest | ||
| from .scam_detector import analyze_text_for_scams | ||
|
|
||
| class TestScamDetector(unittest.TestCase): | ||
|
|
||
| def test_sentiment_analysis(self): | ||
| # Test case for negative sentiment | ||
| text_negative = "This is a terrible, awful, no good, very bad message." | ||
| result_negative = analyze_text_for_scams(text_negative) | ||
| self.assertIn("Strong negative sentiment detected in text.", [indicator for indicator in result_negative["indicators_found"]]) | ||
|
|
||
| # Test case for positive sentiment | ||
| text_positive = "This is a wonderful, amazing, great message." | ||
| result_positive = analyze_text_for_scams(text_positive) | ||
| self.assertNotIn("Strong negative sentiment detected in text.", [indicator for indicator in result_positive["indicators_found"]]) | ||
|
Comment on lines
+10
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (code-quality): Replace identity comprehension with call to collection constructor [×2] ( ExplanationConvert list/set/tuple comprehensions that do not change the input elements into.Before# List comprehensions
[item for item in coll]
[item for item in friends.names()]
# Dict comprehensions
{k: v for k, v in coll}
{k: v for k, v in coll.items()} # Only if we know coll is a `dict`
# Unneeded call to `.items()`
dict(coll.items()) # Only if we know coll is a `dict`
# Set comprehensions
{item for item in coll}After# List comprehensions
list(iter(coll))
list(iter(friends.names()))
# Dict comprehensions
dict(coll)
dict(coll)
# Unneeded call to `.items()`
dict(coll)
# Set comprehensions
set(coll)All these comprehensions are just creating a copy of the original collection. Before# List comprehensions
[item for item in coll]
[item for item in friends.names()]
# Dict comprehensions
{k: v for k, v in coll}
{k: v for k, v in coll.items()} # Only if we know coll is a `dict`
# Unneeded call to `.items()`
dict(coll.items()) # Only if we know coll is a `dict`
# Set comprehensions
{item for item in coll}After# List comprehensions
list(iter(coll))
list(iter(friends.names()))
# Dict comprehensions
dict(coll)
dict(coll)
# Unneeded call to `.items()`
dict(coll)
# Set comprehensions
set(coll)All these comprehensions are just creating a copy of the original collection. |
||
|
|
||
| def test_keyword_matching(self): | ||
| # Test case for urgency keyword | ||
| text_urgency = "URGENT: Your account has been compromised." | ||
| result_urgency = analyze_text_for_scams(text_urgency) | ||
| self.assertIn("Presence of 'Urgency' keyword: 'urgent'", [indicator for indicator in result_urgency["indicators_found"]]) | ||
|
|
||
| # Test case for stemming | ||
| text_stemming = "I need you to verify your account immediately." | ||
| result_stemming = analyze_text_for_scams(text_stemming) | ||
| self.assertIn("Presence of 'Sensitive Info' keyword: 'verify your account'", [indicator for indicator in result_stemming["indicators_found"]]) | ||
|
|
||
| if __name__ == '__main__': | ||
| unittest.main() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| import React, { useState } from 'react'; | ||
|
|
||
| function FakeNewsAnalyzer() { | ||
| const [url, setUrl] = useState(''); | ||
| const [result, setResult] = useState(null); | ||
| const [loading, setLoading] = useState(false); | ||
|
|
||
| const handleAnalyze = () => { | ||
| setLoading(true); | ||
| fetch('/analyze/fake-news', { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| body: JSON.stringify({ url }), | ||
| }) | ||
| .then((res) => res.json()) | ||
| .then((data) => { | ||
| setResult(data); | ||
| setLoading(false); | ||
| }) | ||
| .catch((error) => { | ||
| console.error('Error:', error); | ||
| setLoading(false); | ||
| }); | ||
| }; | ||
|
|
||
| return ( | ||
| <div> | ||
| <h2>Fake News Analyzer</h2> | ||
| <input | ||
| type="text" | ||
| value={url} | ||
| onChange={(e) => setUrl(e.target.value)} | ||
| placeholder="Enter a news URL to analyze..." | ||
| size="50" | ||
| /> | ||
| <br /> | ||
| <button onClick={handleAnalyze} disabled={loading}> | ||
| {loading ? 'Analyzing...' : 'Analyze'} | ||
| </button> | ||
| {result && ( | ||
| <div> | ||
| <h3>Analysis Results</h3> | ||
| {result.error ? ( | ||
| <p>Error: {result.error}</p> | ||
| ) : ( | ||
| <> | ||
| <p>Score: {result.score}</p> | ||
| <h4>Indicators Found:</h4> | ||
| <ul> | ||
| {result.indicators_found.map((indicator, index) => ( | ||
| <li key={index}>{indicator}</li> | ||
| ))} | ||
| </ul> | ||
| {result.named_entities && ( | ||
| <> | ||
| <h4>Named Entities Found:</h4> | ||
| <h5>Organizations:</h5> | ||
| <ul> | ||
| {result.named_entities.organizations.map((org, index) => ( | ||
| <li key={index}>{org}</li> | ||
| ))} | ||
| </ul> | ||
| <h5>Persons:</h5> | ||
| <ul> | ||
| {result.named_entities.persons.map((person, index) => ( | ||
| <li key={index}>{person}</li> | ||
| ))} | ||
| </ul> | ||
| </> | ||
| )} | ||
| </> | ||
| )} | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| export default FakeNewsAnalyzer; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| import React, { useState } from 'react'; | ||
|
|
||
| function ScamAnalyzer() { | ||
| const [text, setText] = useState(''); | ||
| const [result, setResult] = useState(null); | ||
| const [loading, setLoading] = useState(false); | ||
|
|
||
| const handleAnalyze = () => { | ||
| setLoading(true); | ||
| fetch('/analyze/scam', { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| body: JSON.stringify({ text }), | ||
| }) | ||
| .then((res) => res.json()) | ||
| .then((data) => { | ||
| setResult(data); | ||
| setLoading(false); | ||
| }) | ||
| .catch((error) => { | ||
| console.error('Error:', error); | ||
| setLoading(false); | ||
| }); | ||
| }; | ||
|
|
||
| return ( | ||
| <div> | ||
| <h2>Scam Analyzer</h2> | ||
| <textarea | ||
| rows="10" | ||
| cols="50" | ||
| value={text} | ||
| onChange={(e) => setText(e.target.value)} | ||
| placeholder="Paste a message to analyze for scams..." | ||
| /> | ||
| <br /> | ||
| <button onClick={handleAnalyze} disabled={loading}> | ||
| {loading ? 'Analyzing...' : 'Analyze'} | ||
| </button> | ||
| {result && ( | ||
| <div> | ||
| <h3>Analysis Results</h3> | ||
| <p>Score: {result.score}</p> | ||
| <h4>Indicators Found:</h4> | ||
| <ul> | ||
| {result.indicators_found.map((indicator, index) => ( | ||
| <li key={index}>{indicator}</li> | ||
| ))} | ||
| </ul> | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| export default ScamAnalyzer; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,28 +1,36 @@ | ||
| from flask import Flask, request, jsonify | ||
| from social_media_analyzer import scam_detector, fake_news_detector | ||
| import os | ||
|
|
||
| app = Flask(__name__) | ||
|
|
||
| @app.route("/") | ||
| def hello(): | ||
| return "Hello, World!" | ||
| def get_api_key(): | ||
| """Gets the Google API key from environment variables.""" | ||
| return os.environ.get("GOOGLE_API_KEY") | ||
|
|
||
| @app.route('/analyze', methods=['POST']) | ||
| def analyze(): | ||
| @app.route('/analyze/scam', methods=['POST']) | ||
| def analyze_scam(): | ||
| data = request.get_json() | ||
| if not data or 'text' not in data: | ||
| return jsonify({'error': 'Invalid input, "text" field is required.'}), 400 | ||
| return jsonify({"error": "Missing 'text' in request body"}), 400 | ||
|
|
||
| text_to_analyze = data['text'] | ||
| api_key = get_api_key() | ||
|
|
||
| # Placeholder analysis logic | ||
| is_suspicious = 'phishing' in text_to_analyze.lower() | ||
| result = scam_detector.analyze_text_for_scams(text_to_analyze, api_key=api_key) | ||
| return jsonify(result) | ||
|
|
||
| @app.route('/analyze/fake-news', methods=['POST']) | ||
| def analyze_fake_news(): | ||
| data = request.get_json() | ||
| if not data or 'url' not in data: | ||
| return jsonify({"error": "Missing 'url' in request body"}), 400 | ||
|
|
||
| url_to_analyze = data['url'] | ||
|
|
||
| result = fake_news_detector.analyze_url_for_fake_news(url_to_analyze) | ||
| return jsonify(result) | ||
|
|
||
| return jsonify({ | ||
| 'text': text_to_analyze, | ||
| 'analysis': { | ||
| 'is_suspicious': is_suspicious | ||
| } | ||
| }) | ||
|
|
||
| if __name__ == "__main__": | ||
| app.run(host="0.0.0.0", port=8080) | ||
| if __name__ == '__main__': | ||
| app.run(debug=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: Named entity extraction does not handle cases where NLTK data is missing.
Catch NLTK exceptions and provide a user-friendly error message or guidance on downloading missing data.