1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 20:42:21 +02:00
Beef/IDE/src/WakaTime.bf

294 lines
8.7 KiB
Beef

using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Beefy;
namespace IDE
{
public class WakaTime
{
String mApiKey ~ delete _;
String mPythonLocation ~ delete _;
String mCurFilePath = new String() ~ delete _;
int32 mLastSendTicks;
Monitor mMonitor = new Monitor() ~ delete _;
public this(String key)
{
mApiKey = new String(key);
}
public void Dispose()
{
}
public void QueueFile(String filePath, String projectName, bool isWrite)
{
String useFilePath = filePath;
String useProjectName = projectName;
bool doSend = false;
if (mCurFilePath != useFilePath)
{
doSend = true;
}
else if (mLastSendTicks > 120*60)
{
doSend = true;
}
if (isWrite)
doSend = true;
mCurFilePath.Set(useFilePath);
if (doSend)
{
useFilePath = new String(useFilePath);
useProjectName = new String(useProjectName);
var me = this;
ThreadPool.QueueUserWorkItem(new () => me.SendFile(useFilePath, useProjectName, isWrite) ~ { delete useFilePath; delete useProjectName; });
mLastSendTicks = 0;
}
}
public void Update()
{
mLastSendTicks++;
}
public void getPythonDir(String pyDir)
{
getCurrentDirectory(pyDir);
pyDir.Append("\\Python");
}
public void getPython(String outPath)
{
doesPythonExist();
//return;
if (mPythonLocation != null)
{
outPath.Append(mPythonLocation);
return;
}
String[] locations = scope
.(
//"c:\\Python27\\python.exe",
"pythonw.exe",
"python",
"\\Python37\\pythonw",
"\\Python36\\pythonw",
"\\Python35\\pythonw",
"\\Python34\\pythonw",
"\\Python33\\pythonw",
"\\Python32\\pythonw",
"\\Python31\\pythonw",
"\\Python30\\pythonw",
"\\Python27\\pythonw",
"\\Python26\\pythonw",
"\\python37\\pythonw",
"\\python36\\pythonw",
"\\python35\\pythonw",
"\\python34\\pythonw",
"\\python33\\pythonw",
"\\python32\\pythonw",
"\\python31\\pythonw",
"\\python30\\pythonw",
"\\python27\\pythonw",
"\\python26\\pythonw",
"\\Python37\\python",
"\\Python36\\python",
"\\Python35\\python",
"\\Python34\\python",
"\\Python33\\python",
"\\Python32\\python",
"\\Python31\\python",
"\\Python30\\python",
"\\Python27\\python",
"\\Python26\\python",
"\\python37\\python",
"\\python36\\python",
"\\python35\\python",
"\\python34\\python",
"\\python33\\python",
"\\python32\\python",
"\\python31\\python",
"\\python30\\python",
"\\python27\\python",
"\\python26\\python"
);
for (String location in locations)
{
if (location.Contains('\\'))
{
String dirName = scope String();
Path.GetDirectoryPath(location, dirName);
if (!Directory.Exists(dirName))
continue;
}
ProcessStartInfo procInfo = scope ProcessStartInfo();
procInfo.UseShellExecute = false;
procInfo.RedirectStandardError = true;
procInfo.RedirectStandardOutput = true;
procInfo.SetFileName(location);
procInfo.CreateNoWindow = true;
procInfo.SetArguments("--version");
Debug.WriteLine("ProcStartInfo {0} Verb: {1}", procInfo, procInfo.[Friend]mVerb);
/*Process process = null;
if (!case .Ok(out process) = Process.Start(procInfo))
continue;
defer(scope) delete process;
String errors = scope String();
if (case .Err = process.StandardError.ReadToEnd(errors))
continue;*/
String resultStr = scope String();
SpawnedProcess process = scope SpawnedProcess();
if (process.Start(procInfo) case .Err)
continue;
FileStream fileStream = scope FileStream();
process.AttachStandardError(fileStream);
StreamReader streamReader = scope StreamReader(fileStream, null, false, 4096);
streamReader.ReadToEnd(resultStr).IgnoreError();
if (resultStr.IsEmpty)
{
FileStream fileStreamOut = scope FileStream();
process.AttachStandardOutput(fileStreamOut);
StreamReader streamReaderOut = scope StreamReader(fileStreamOut, null, false, 4096);
streamReaderOut.ReadToEnd(resultStr).IgnoreError();
}
//TODO: This 'errors' check is not correct, but also it seems that we're getting stdout data in stderr... (?)
if ((resultStr != null) && (resultStr != ""))
{
mPythonLocation = new String(location);
outPath.Append(mPythonLocation);
return;
}
}
mPythonLocation = new String("");// Give up
return;
}
void GetCLI(String cliPath)
{
cliPath.Append(BFApp.sApp.mInstallDir, "wakatime-master/wakatime/cli.py");
}
SpawnedProcess mProcess ~ delete _;
public void SendFile(String fileName, String projectName, bool isWrite)
{
using (mMonitor.Enter())
{
DoSendFile(fileName, projectName, isWrite);
}
}
public void DoSendFile(String fileName, String projectName, bool isWrite)
{
Debug.WriteLine("WakaTime: {0} proj: {1} isWrite: {2} ThreadId: {3} Tick: {4}", fileName, projectName, isWrite, Thread.CurrentThread.Id, (int32)Platform.BfpSystem_TickCount());
String arguments = scope String();
arguments.Append("\"");
GetCLI(arguments);
arguments.Append("\" --key=\"", mApiKey, "\"",
" --file=\"", fileName, "\"",
" --plugin=\"Beef\"");
if (!String.IsNullOrWhiteSpace(projectName))
arguments.Append(" --project=\"", projectName, "\"");
if (isWrite)
arguments.Append(" --write");
ProcessStartInfo procInfo = scope ProcessStartInfo();
procInfo.UseShellExecute = false;
String pyPath = scope String();
getPython(pyPath);
if (String.IsNullOrEmpty(pyPath))
return;
procInfo.SetFileName(pyPath);
procInfo.CreateNoWindow = true;
procInfo.SetArguments(arguments);
//for (int i = 0; i < 10; i++)
{
//Debug.WriteLine("ProcStartInfo {0} Dir: {1} Verb: {2}", procInfo, procInfo.mDirectory, procInfo.mVerb);
delete mProcess;
mProcess = new SpawnedProcess();
if (mProcess.Start(procInfo) case .Err)
{
delete mProcess;
mProcess = null;
}
}
}
/// Check if wakatime command line exists or not
bool doesCLIExist()
{
String path = scope String();
GetCLI(path);
if (File.Exists(path))
{
return true;
}
return false;
}
/// Check if bundled python installation exists
bool doesPythonExist()
{
String path = scope String();
getPythonDir(path);
path.Append("\\pythonw.exe");
if (File.Exists(path))
{
return true;
}
return false;
}
/// Check if python is installed
bool isPythonInstalled()
{
String pyPath = scope String();
getPython(pyPath);
if (String.IsNullOrEmpty(pyPath))
{
return true;
}
return false;
}
/// Returns current working dir
static public void getCurrentDirectory(String outDir)
{
var exePath = scope String();
Environment.GetExecutableFilePath(exePath);
Path.GetDirectoryPath(exePath, outDir);
}
}
}