|
@@ -1,5 +1,11 @@
|
|
|
package de.nplusc.izc.senabitwiggler;
|
|
|
|
|
|
+import io.github.ma1uta.matrix.client.StandaloneClient;
|
|
|
+import io.github.ma1uta.matrix.client.model.room.CreateRoomRequest;
|
|
|
+import io.github.ma1uta.matrix.event.content.RoomPowerLevelsContent;
|
|
|
+import io.github.ma1uta.matrix.impl.exception.MatrixException;
|
|
|
+import org.apache.logging.log4j.LogManager;
|
|
|
+import org.apache.logging.log4j.Logger;
|
|
|
import org.yaml.snakeyaml.DumperOptions;
|
|
|
import org.yaml.snakeyaml.TypeDescription;
|
|
|
import org.yaml.snakeyaml.Yaml;
|
|
@@ -12,17 +18,19 @@ import java.io.*;
|
|
|
import java.nio.file.CopyOption;
|
|
|
import java.nio.file.Files;
|
|
|
import java.nio.file.StandardCopyOption;
|
|
|
+import java.text.DateFormat;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
import java.util.*;
|
|
|
|
|
|
public class FirmwareAutoDumper
|
|
|
{
|
|
|
-
|
|
|
+ private static final Logger l = LogManager.getLogger();
|
|
|
static Statefile state = null;
|
|
|
static File outfolder_base;
|
|
|
public static final boolean IA_UPLOAD_ENABLED = false;
|
|
|
public static final boolean DUMMY_MODE = false;
|
|
|
public static PrintStream dummydownloadfake = null;
|
|
|
- public static Set<String> supprCache = new HashSet<>();
|
|
|
+ public static HashMap<String,FirmwareVersion> supprCache = new HashMap<>();
|
|
|
|
|
|
public static void pullFirmwares(File statefile, File outfolder, boolean deepmode)
|
|
|
{
|
|
@@ -32,6 +40,7 @@ public class FirmwareAutoDumper
|
|
|
{
|
|
|
dummydownloadfake = new PrintStream(new FileOutputStream(new File(outfolder,"dummy.log")));
|
|
|
}
|
|
|
+
|
|
|
Representer representer = new Representer();
|
|
|
representer.addClassTag(Firmware.class, new Tag("!FW"));
|
|
|
representer.addClassTag(FirmwareVersion.class, new Tag("!FWV"));
|
|
@@ -49,8 +58,7 @@ public class FirmwareAutoDumper
|
|
|
Yaml internal = new Yaml(constructor);
|
|
|
state = (Statefile) internal.load(new FileReader(statefile));
|
|
|
} catch (FileNotFoundException e) {
|
|
|
- System.err.println("Hurz");
|
|
|
- e.printStackTrace();
|
|
|
+ l.catching(e);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
@@ -60,6 +68,10 @@ public class FirmwareAutoDumper
|
|
|
}
|
|
|
|
|
|
File outfolder_tmp = new File(outfolder,"tmp");
|
|
|
+ if(!DUMMY_MODE)
|
|
|
+ {
|
|
|
+ new File(outfolder_tmp,"Firmware").delete();
|
|
|
+ }
|
|
|
File downloadFolderBase = new File(outfolder_base,"downloadstage");
|
|
|
downloadFolderBase.mkdirs();
|
|
|
File fw = new File(outfolder_tmp,"Firmware");
|
|
@@ -129,11 +141,16 @@ public class FirmwareAutoDumper
|
|
|
br.close();
|
|
|
y.dump(state,new FileWriter(statefile));
|
|
|
if(!DUMMY_MODE)
|
|
|
+ {
|
|
|
new File(outfolder_tmp,"Firmware").delete();
|
|
|
+ pushToMatrix();
|
|
|
+ }
|
|
|
if(DUMMY_MODE)
|
|
|
{
|
|
|
dummydownloadfake.close();
|
|
|
}
|
|
|
+
|
|
|
+ y.dump(state,new FileWriter(statefile));
|
|
|
}
|
|
|
catch (IOException ex)
|
|
|
{
|
|
@@ -141,6 +158,138 @@ public class FirmwareAutoDumper
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private static void pushToMatrix()
|
|
|
+ {
|
|
|
+ if(!EntryPoint.c.isMatrixEnabled())
|
|
|
+ {
|
|
|
+ //skip all if matrix is off.
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ StandaloneClient mxClient = new StandaloneClient.Builder().domain(EntryPoint.c.getMatrixDomain()).build();
|
|
|
+ mxClient.auth().login(EntryPoint.c.getMatrixUser(), EntryPoint.c.getMatrixPassword().toCharArray());
|
|
|
+ if(state.getGeneralRoomId()==null)
|
|
|
+ {
|
|
|
+ l.info("Create Matrix Room General");
|
|
|
+ CreateRoomRequest r = new CreateRoomRequest();
|
|
|
+ r.setName("Sena Full Logstream");
|
|
|
+ r.setRoomAliasName("SenaFirmwareAll");
|
|
|
+ RoomPowerLevelsContent lvls = new RoomPowerLevelsContent();
|
|
|
+ lvls.setEventsDefault((byte)1); //readonly except for the BitWiggler
|
|
|
+ r.setPowerLevelContentOverride(lvls);
|
|
|
+ r.setVisibility("public");
|
|
|
+ state.setGeneralRoomId(mxClient.room().create(r).getRoomId());
|
|
|
+ }
|
|
|
+
|
|
|
+ if(state.getOtherRoomId()==null)
|
|
|
+ {
|
|
|
+ l.info("Create Matrix Room Catchall");
|
|
|
+ CreateRoomRequest r = new CreateRoomRequest();
|
|
|
+ r.setName("Sena Other Logstream");
|
|
|
+ r.setRoomAliasName("SenaFirmwareOther");
|
|
|
+ RoomPowerLevelsContent lvls = new RoomPowerLevelsContent();
|
|
|
+ lvls.setEventsDefault((byte)1); //readonly except for the BitWiggler
|
|
|
+ r.setPowerLevelContentOverride(lvls);
|
|
|
+ r.setVisibility("public");
|
|
|
+ state.setOtherRoomId(mxClient.room().create(r).getRoomId());
|
|
|
+ }
|
|
|
+
|
|
|
+ state.getFirmwares().forEach((k,v)->
|
|
|
+ {
|
|
|
+ if(v.getRoomid()==null)
|
|
|
+ {
|
|
|
+ l.info("Create Matrix Room for:"+k);
|
|
|
+ CreateRoomRequest r = new CreateRoomRequest();
|
|
|
+ r.setName("Sena Logstream: "+v.getDeviceId());
|
|
|
+ r.setRoomAliasName("SenaStream"+k);
|
|
|
+ RoomPowerLevelsContent lvls = new RoomPowerLevelsContent();
|
|
|
+ lvls.setEventsDefault((byte)1); //readonly except for the BitWiggler
|
|
|
+ r.setPowerLevelContentOverride(lvls);
|
|
|
+ r.setVisibility("public");
|
|
|
+ while(v.getRoomid()==null)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+
|
|
|
+ v.setRoomid(mxClient.room().create(r).getRoomId());
|
|
|
+ }
|
|
|
+ catch(MatrixException e)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ if(v.getRoomid()==null)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ Thread.sleep(2000);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> keys = new ArrayList<>(v.getVersions().keySet());
|
|
|
+ keys.sort((x,y)->
|
|
|
+ {
|
|
|
+ var vr = v.getVersions();
|
|
|
+ var version1 = vr.get(x);
|
|
|
+ var version2 = vr.get(y);
|
|
|
+ if(version1.getMajor()< version2.getMajor()) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if(version1.getMajor()> version2.getMajor()) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ if(version1.getMinor()< version2.getMinor()) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if(version1.getMinor()> version2.getMinor()) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ if(version1.getPatch()< version2.getPatch()) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if(version1.getPatch()> version2.getPatch()) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ });
|
|
|
+ for (var v2p : keys) {
|
|
|
+ final var v2 = v.getVersions().get(v2p); //HAXX
|
|
|
+ LinkedList<Runnable> messageActions = new LinkedList<>();
|
|
|
+
|
|
|
+ if(!v2.isFiller())
|
|
|
+ {
|
|
|
+ String version = v2.getMajor()+"."+v2.getMinor()+"."+v2.getPatch();
|
|
|
+ Date ts = v2.getServerCreationDate();
|
|
|
+ TimeZone tz = TimeZone.getTimeZone("UTC");
|
|
|
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); // Quoted "Z" to indicate UTC, no timezone offset
|
|
|
+ df.setTimeZone(tz);
|
|
|
+ String date = df.format(ts);
|
|
|
+ String msg = "Detected new Version: "+version+" for "+k+" uploaded at: "+date;
|
|
|
+
|
|
|
+ if(v2.isHidden())
|
|
|
+ {
|
|
|
+ msg = "Guessed new hidden Version: "+version+" for "+k+" uploaded at: "+date;
|
|
|
+ }
|
|
|
+ if((!v2.isHidden()&&v2.getNotificationState()==MatrixState.SENT_PRELIM)||v2.getNotificationState()==MatrixState.TODO)
|
|
|
+ {
|
|
|
+ final String msg2 = msg;
|
|
|
+ messageActions.add(()->
|
|
|
+ {
|
|
|
+ l.info("Push: "+msg2);
|
|
|
+ mxClient.event().sendMessage(v.getRoomid(), msg2);
|
|
|
+ mxClient.event().sendMessage(state.getGeneralRoomId(), msg2);
|
|
|
+ v2.setNotificationState(v2.isHidden()?MatrixState.SENT_PRELIM:MatrixState.SENT);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ messageActions.iterator().forEachRemaining(runnable -> runnable.run());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ mxClient.auth().logout();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
private static int[] splitVersionAndPullFW(String filename,HashMap<String,FirmwareVersion> knownVersions, boolean deepmode) throws IOException {
|
|
|
String[] magic = filename.split("-v");
|
|
|
boolean fuckingoddity = false;
|
|
@@ -213,9 +362,9 @@ public class FirmwareAutoDumper
|
|
|
String prefix,
|
|
|
String suffix,
|
|
|
HashMap<String,FirmwareVersion> knownVersions) throws IOException {
|
|
|
- System.out.println(major+"--"+minor+"--"+patch);
|
|
|
+ l.info(major+"--"+minor+"--"+patch);
|
|
|
List<FirmwareVersion> temp = new ArrayList<>();
|
|
|
- System.out.println(prefix+"."+major+"."+minor+"."+patch+"."+suffix);
|
|
|
+ l.info(prefix+"."+major+"."+minor+"."+patch+"."+suffix);
|
|
|
|
|
|
while(major>=1&&minor>=0&&patch>=0) //older versions won't be bruteforced, check for existence in the index prevents a redownload.
|
|
|
{
|
|
@@ -266,13 +415,15 @@ public class FirmwareAutoDumper
|
|
|
f.setMinor(minor);
|
|
|
f.setPatch(patch);
|
|
|
File downloadFolderBase = new File(outfolder_base,"downloadstage");
|
|
|
- if(supprCache.contains(fwname)) //leaves a "fake entry" when 2 different deviceIDs would lead to the same filename
|
|
|
+ if(supprCache.containsKey(fwname)) //leaves a "fake entry" when 2 different deviceIDs would lead to the same filename
|
|
|
{
|
|
|
- f.setFiller(true);
|
|
|
- f.setServerCreationDate(new Date(0));
|
|
|
+ l.info("Fakerfuck");
|
|
|
+ FirmwareVersion f2 = supprCache.get(fwname);
|
|
|
+ f.setFiller(false);
|
|
|
+ f.setServerCreationDate(f2.getServerCreationDate());
|
|
|
return f;
|
|
|
}
|
|
|
- supprCache.add(fwname); // banning a filename from rescan/redownload
|
|
|
+ supprCache.put(fwname,f); // banning a filename from rescan/redownload
|
|
|
//if(true) return f;
|
|
|
if(!DUMMY_MODE)
|
|
|
{
|
|
@@ -285,24 +436,16 @@ public class FirmwareAutoDumper
|
|
|
{
|
|
|
dummydownloadfake.println("http://firmware.sena.com/senabluetoothmanager/"+fwname);
|
|
|
}
|
|
|
- System.err.println("New Version spotted:"+fwname); //intentionally a output. that should be mailed by the cron daemon if its
|
|
|
+ l.info("New Version spotted:"+fwname);
|
|
|
File dlf = new File(downloadFolderBase,fwname);
|
|
|
File dst = new File(outfolder_base,fwname);
|
|
|
- if(dlf.exists()&&!dst.exists())
|
|
|
+ if(dlf.exists())
|
|
|
{
|
|
|
f.setFiller(false);
|
|
|
f.setServerCreationDate(new Date(dlf.lastModified()));
|
|
|
- Files.copy(dlf.toPath(),dst.toPath());
|
|
|
-
|
|
|
- if(IA_UPLOAD_ENABLED)
|
|
|
+ if(!dst.exists())
|
|
|
{
|
|
|
- Utils.runTool(downloadFolderBase,
|
|
|
- "ia",
|
|
|
- "upload",
|
|
|
- "sena-firmware-files",
|
|
|
- "--no-derive",
|
|
|
- fwname
|
|
|
- );
|
|
|
+ Files.copy(dlf.toPath(),dst.toPath());
|
|
|
}
|
|
|
}
|
|
|
else
|
|
@@ -314,6 +457,9 @@ public class FirmwareAutoDumper
|
|
|
}
|
|
|
|
|
|
private static void peekNext(String synthesizedFileName, String synthesizedFileNameShort, int major, int minor, int patch, HashMap<String,FirmwareVersion> knownVersions) throws IOException {
|
|
|
+ l.info("peekstate:");
|
|
|
+ l.info(knownVersions.containsKey(synthesizedFileName));
|
|
|
+ l.info(knownVersions.containsKey(synthesizedFileNameShort));
|
|
|
if(!(knownVersions.containsKey(synthesizedFileName)||knownVersions.containsKey(synthesizedFileNameShort))) // only re-poking if nothing was there yet.
|
|
|
{
|
|
|
FirmwareVersion nextMajor = getFirmware(major,minor,patch,true,synthesizedFileName);
|
|
@@ -325,8 +471,10 @@ public class FirmwareAutoDumper
|
|
|
synthesizedFileName = synthesizedFileNameShort;
|
|
|
}
|
|
|
}
|
|
|
+ l.info("peekstate:"+nextMajor.isFiller());
|
|
|
if(!nextMajor.isFiller())
|
|
|
{
|
|
|
+ l.info("SUCCESS for:"+synthesizedFileName);
|
|
|
knownVersions.put(synthesizedFileName,nextMajor);
|
|
|
}
|
|
|
}
|