Add feed aggregation and embedding generation features
This commit is contained in:
@@ -1,10 +1,235 @@
|
||||
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:uid/uid.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'dart:io';
|
||||
|
||||
class SettingsProvider extends ChangeNotifier {
|
||||
|
||||
String _OPENAI_API_KEY = "";
|
||||
String get openAIApiKey => _OPENAI_API_KEY;
|
||||
|
||||
List<Feed> _feeds = [
|
||||
// Major Business News
|
||||
Feed(
|
||||
title: "Business Insider",
|
||||
url: "https://feeds.businessinsider.com/custom/all"
|
||||
),
|
||||
Feed(
|
||||
title: "BBC Business",
|
||||
url: "https://feeds.bbci.co.uk/news/business/rss.xml"
|
||||
),
|
||||
Feed(
|
||||
title: "Reuters Business",
|
||||
url: "https://www.reutersagency.com/feed/?taxonomy=best-topics&post_type=best"
|
||||
),
|
||||
Feed(
|
||||
title: "Financial Times",
|
||||
url: "https://www.ft.com/?format=rss"
|
||||
),
|
||||
Feed(
|
||||
title: "Bloomberg",
|
||||
url: "https://feeds.bloomberg.com/markets/news.rss"
|
||||
),
|
||||
|
||||
// Market-Specific
|
||||
Feed(
|
||||
title: "MarketWatch",
|
||||
url: "https://feeds.marketwatch.com/marketwatch/topstories/"
|
||||
),
|
||||
Feed(
|
||||
title: "Seeking Alpha",
|
||||
url: "https://seekingalpha.com/feed.xml"
|
||||
),
|
||||
Feed(
|
||||
title: "Yahoo Finance",
|
||||
url: "https://finance.yahoo.com/news/rssindex"
|
||||
),
|
||||
Feed(
|
||||
title: "CNBC",
|
||||
url: "https://www.cnbc.com/id/100003114/device/rss/rss.html"
|
||||
),
|
||||
Feed(
|
||||
title: "The Wall Street Journal",
|
||||
url: "https://feeds.a.dj.com/rss/RSSMarketsMain.xml"
|
||||
),
|
||||
|
||||
// Tech Business
|
||||
Feed(
|
||||
title: "TechCrunch",
|
||||
url: "https://techcrunch.com/feed/"
|
||||
),
|
||||
Feed(
|
||||
title: "The Verge",
|
||||
url: "https://www.theverge.com/rss/index.xml"
|
||||
),
|
||||
Feed(
|
||||
title: "Ars Technica",
|
||||
url: "https://feeds.arstechnica.com/arstechnica/index"
|
||||
),
|
||||
|
||||
// Company News
|
||||
Feed(
|
||||
title: "Fortune",
|
||||
url: "https://fortune.com/feed"
|
||||
),
|
||||
Feed(
|
||||
title: "Forbes Business",
|
||||
url: "https://www.forbes.com/business/feed/"
|
||||
),
|
||||
Feed(
|
||||
title: "Inc Magazine",
|
||||
url: "https://www.inc.com/rss"
|
||||
),
|
||||
|
||||
// Industry-Specific
|
||||
Feed(
|
||||
title: "Retail Dive",
|
||||
url: "https://www.retaildive.com/feeds/news/"
|
||||
),
|
||||
Feed(
|
||||
title: "Manufacturing Dive",
|
||||
url: "https://www.manufacturingdive.com/feeds/news/"
|
||||
),
|
||||
Feed(
|
||||
title: "Banking Dive",
|
||||
url: "https://www.bankingdive.com/feeds/news/"
|
||||
),
|
||||
|
||||
// Economic News
|
||||
Feed(
|
||||
title: "The Economist",
|
||||
url: "https://www.economist.com/finance-and-economics/rss.xml"
|
||||
),
|
||||
Feed(
|
||||
title: "Federal Reserve News",
|
||||
url: "https://www.federalreserve.gov/feeds/press_all.xml"
|
||||
),
|
||||
]; // List of rss feed URLs
|
||||
List<Feed> get feeds => List.unmodifiable(_feeds);
|
||||
|
||||
late String _applicationStorageLocation;
|
||||
String get applicationStorageLocation => _applicationStorageLocation;
|
||||
|
||||
static SettingsProvider of(BuildContext context) {
|
||||
return context
|
||||
return Provider.of<SettingsProvider>(context, listen: false);
|
||||
}
|
||||
|
||||
}ç
|
||||
Future<void> load() async {
|
||||
// get documents directory dynamicly
|
||||
final Directory appDocDir = await getApplicationDocumentsDirectory();
|
||||
_applicationStorageLocation = appDocDir.path;
|
||||
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
|
||||
_OPENAI_API_KEY = prefs.getString('openai_api_key') ?? _OPENAI_API_KEY;
|
||||
|
||||
List<String>? feedStrings = prefs.getStringList('feeds');
|
||||
if (feedStrings != null) {
|
||||
_feeds = feedStrings.map((fStr) {
|
||||
try {
|
||||
return Feed.fromJson(jsonDecode(fStr));
|
||||
} catch (e) {
|
||||
// old format, parse manually
|
||||
Map<String, dynamic> json = {};
|
||||
fStr.substring(1, fStr.length - 1).split(', ').forEach((pair) {
|
||||
List<String> keyValue = pair.split(': ');
|
||||
String key = keyValue[0];
|
||||
String value = keyValue[1];
|
||||
|
||||
// convert bool strings to actual bools
|
||||
if (value == 'true') {
|
||||
json[key] = true;
|
||||
} else if (value == 'false') {
|
||||
json[key] = false;
|
||||
} else {
|
||||
json[key] = value;
|
||||
}
|
||||
});
|
||||
return Feed.fromJson(json);
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
|
||||
_applicationStorageLocation = prefs.getString('application_storage_location') ?? applicationStorageLocation;
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> save() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
|
||||
await prefs.setString('openai_api_key', _OPENAI_API_KEY);
|
||||
await prefs.setStringList('feeds', _feeds.map((f) => jsonEncode(f.toJson())).toList());
|
||||
await prefs.setString('application_storage_location', _applicationStorageLocation);
|
||||
}
|
||||
|
||||
void setOpenAIApiKey(String key) {
|
||||
_OPENAI_API_KEY = key;
|
||||
save();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void addFeed(Feed feed) {
|
||||
_feeds.add(feed);
|
||||
save();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Feed updateFeed(int id, {String? title, String? url, bool? enabled}) {
|
||||
for (int i = 0; i < _feeds.length; i++) {
|
||||
if (_feeds[i].id == id) {
|
||||
Feed updatedFeed = Feed(
|
||||
url: url ?? _feeds[i].url,
|
||||
title: title ?? _feeds[i].title,
|
||||
enabled: enabled ?? _feeds[i].enabled,
|
||||
);
|
||||
_feeds[i] = updatedFeed;
|
||||
save();
|
||||
notifyListeners();
|
||||
return updatedFeed;
|
||||
}
|
||||
}
|
||||
throw Exception("Feed with id $id not found");
|
||||
}
|
||||
|
||||
void removeFeed(Feed feed) {
|
||||
_feeds.removeWhere((f) => f.url == feed.url);
|
||||
save();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setApplicationStorageLocation(String path) {
|
||||
_applicationStorageLocation = path;
|
||||
save();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Feed {
|
||||
|
||||
final String url;
|
||||
final String title;
|
||||
final bool enabled;
|
||||
|
||||
Feed({required this.url, required this.title, this.enabled = true});
|
||||
|
||||
Feed.fromJson(Map<String, dynamic> json)
|
||||
: url = json['url'],
|
||||
title = json['title'],
|
||||
enabled = json['enabled'] ?? true;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'url': url,
|
||||
'title': title,
|
||||
'enabled': enabled,
|
||||
};
|
||||
|
||||
int get id {
|
||||
return url.hashCode ^ title.hashCode;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user