toolheim/mobile-app/lib/github_reader.dart

116 lines
3.6 KiB
Dart

import 'dart:collection';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:toolheim/warband_roaster.dart';
import 'package:yaml/yaml.dart';
enum SyncState {
unknown,
running,
success,
error,
}
class GitHubAdapter {
// TODO: Store this in the SharedPreferences
final String repository;
final String path;
static SyncState syncState = SyncState.unknown;
List<String> syncErrors = new List<String>();
static DateTime lastSync;
GitHubAdapter(this.repository, this.path);
/// Search for warband files in the GitHub repository
///
/// This method will search for matching files and check their content in a
/// subfolder (see fields [repository] and [path]). If the file
/// contain errors or can't read, a sync error message will be written into
/// the [syncErrors] list.
Future<List<WarbandRoaster>> search() async {
syncErrors.clear();
Stream<Map<String, String>> roasterStream() async* {
// Get all files which could be potential warband files (end with
// mordheim.yml and contain the word "heros").
http.Response response = await http.get(
"https://api.github.com/search/code?q=heros+repo:" +
repository +
"+filename:mordheim.yml+path:\"" +
path +
"\"");
RegExp fileRegex = new RegExp(r"[a-zA-Z]+\.mordheim\.ya?ml");
var resp = jsonDecode(response.body);
for (var searchResult in resp['items']) {
if (fileRegex.hasMatch(searchResult['name'])) {
String completePath = searchResult['path'];
String playerName =
completePath.substring(path.length + 1).split('/').first;
if (playerName == '') {
playerName = 'Lonely Recluse';
}
// Fetch last change and some metainformation of the file
http.Response response = await http.get(
"https://api.github.com/repos/" +
repository +
"/commits?path=" +
completePath);
var resp = jsonDecode(response.body);
var lastCommit = resp.first;
// TODO: Add some error handling
yield {
'filePath': completePath.toString(),
'shaHash': lastCommit['sha'],
'player': playerName.toString(),
'author': lastCommit['commit']['author']['name'],
'date': lastCommit['commit']['committer']['date'],
'message': lastCommit['commit']['message']
};
}
}
}
List<WarbandRoaster> roasters = new List<WarbandRoaster>();
// TODO: Read params from share preferences
await for (Map<String, String> player in roasterStream()) {
http.Response response = await http.get(
"https://raw.githubusercontent.com/" +
repository +
'/master/' +
player['filePath']);
try {
YamlMap yamlObject = loadYaml(response.body);
WarbandRoaster roaster = WarbandRoaster.fromJson(yamlObject);
roaster.playerName = player['player'];
roaster.author = player['author'];
roaster.commitDate = player['date'];
roaster.commitMessage = player['message'];
roaster.commitHash = player['shaHash']
roasters.add(roaster);
} catch (e) {
syncErrors.add(e.toString());
}
}
return roasters;
}
Future<SyncState> update() async {
// TODO: Search for warband yml files
// TODO: Check if it is in the right format
// TODO: Store it into the database if valid
lastSync = DateTime.now();
return SyncState.success;
}
}