-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.html
199 lines (173 loc) · 9.86 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Web Browser based JavaScript Online File Extractor, Parser, Unpacker and Zip File Converter for the Snap Camera / Snapchat Lens File Format (lens.lns / *.lns)">
<meta name="keywords" content="Snap Camera,Snapcamera,Snapchat,Snap,Snap Lens,Snap Lenses,Lens,Lenses,lens.lns,extractor,parser,unpacker,zip,converter">
<meta name="author" content="Patrick Trumpis">
<meta name="generator" content="Patrick Trumpis">
<title>Snap Lens File Extractor</title>
<link rel="canonical" href="https://ptrumpis.github.io/snap-lens-file-extractor/">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css" integrity="sha512-c0+vSv9tnGS4fzwTIBFPcdCZ0QwP+aTePvZeAJkYpbj67KvQ5+VrJjDh3lil48LILJxhICQf66dQ8t/BJyOo/g==" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" integrity="sha512-72OVeAaPeV8n3BdZj7hOkaPSEk/uwpDkaGyP4W2jSzAC8tfiO4LMEDWoL3uFp5mcZu+8Eehb4GhZWFwvrss69Q==" crossorigin="anonymous">
<link rel="stylesheet" href="./style.css">
</head>
<body class="text-center text-bg-dark">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark" aria-label="navbar">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-md-center" id="navbar">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="https://ptrumpis.github.io/snap-lens-file-extractor/">👻 Snap Lens File Extractor</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/ptrumpis/snap-lens-file-extractor"><i class="bi bi-github"></i> Source</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://bit.ly/snpcm">Download Snap Camera</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-expanded="false">More Snap Camera Projects</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="https://github.com/ptrumpis/snap-camera-server"><i class="bi bi-github"></i> Snap Camera Server v3</a></li>
<li><a class="dropdown-item" href="https://github.com/ptrumpis/snap-camera-server-auto-config"><i class="bi bi-github"></i> Snap Camera Server Auto Config</a></li>
<li><a class="dropdown-item" href="https://github.com/ptrumpis/snap-lens-tool/"><i class="bi bi-github"></i> Snap Lens Tool</a></li>
<li><a class="dropdown-item" href="https://ptrumpis.github.io/snap-lens-cache-import/"><i class="bi bi-github"></i> Snap Lens Cache Import</a></li>
<li><a class="dropdown-item" href="https://ptrumpis.github.io/snap-camera-signature-patch/"><i class="bi bi-github"></i> Snap Camera Signature Patch</a></li>
<li><a class="dropdown-item" href="https://ptrumpis.github.io/snap-lens-file-format/"><i class="bi bi-github"></i> Snap Lens File Format</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div class="cover-container w-100 h-100 p-3 mx-auto">
<main class="px-3">
<h3>Snap Lens (*.lns) to .zip converter</h3>
<p class="lead">Convert your Snapchat and Snap Camera *.lns files to a zip archive for download and easy file extraction.</p>
<h5 class="mt-5">File Selection</h5>
<div class="container">
<div id="dropDiv">
Drag and Drop your lens.lns file to this area.<br />
Or select your lens.lns file
<input type="file" class="form-control-file mt-2" id="inputFile" name="inputFile" />
</div>
</div>
<h5 class="mt-5">Unpacking Event Log</h5>
<div class="container">
<div class="form-group">
<textarea readonly class="form-control" id="eventLog" rows="8"></textarea>
</div>
</div>
</main>
<footer class="mt-auto text-white-50 py-5">
<p>
This is <a href="https://github.com/ptrumpis/snap-lens-file-extractor" class="link-secondary"><i class="bi bi-github"></i> Snap Lens File Extractor</a>
© 2023 by <a href="https://github.com/ptrumpis" class="link-secondary">Patrick Trumpis</a>.
</p>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha512-Sct/LCTfkoqr7upmX9VZKEzXuRk5YulFoDTunGapYJdlCwA+Rl4RhgcPCLf7awTNLmIVrszTPNUFu4MSesep5Q==" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/gh/ptrumpis/zstd.js@1.5.4/dist/zstd.js" integrity="sha512-TuugAv5n1SUDFAGmk/P+x5ZLsila/v74N8WaF/OLdK0AMIQRSfcxc4VTjeB4TuKAnl2FnpCs3kI7hhUgX5nUMw==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js" integrity="sha512-XMVd28F1oH/O71fzwBnV7HucLxVwtxf26XV8P4wPk26EDxuGZ91N8bsOttmnomcCD3CS5ZMRL50H0GgOHvegtg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js" integrity="sha512-Qlv6VSKh1gDKGoJbnyA5RMXYcvnpIqhO++MhIM2fStMcGT9i2T//tSwYFlcyoRRDcDZ+TYHpH8azBBCyhpSeqw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="./lensparser.js"></script>
<script>
const fileInput = document.querySelector('input[type="file"]');
const dropDiv = document.querySelector('#dropDiv');
const eventLog = document.querySelector('#eventLog');
const reader = new FileReader();
const parser = new LensFileParser();
function handleEvent(event) {
// file reader event log
eventLog.textContent += `${event.type}: ${event.loaded} bytes transferred\n`;
}
function addListeners(reader) {
// log all file reader events (not required debug only)
reader.addEventListener('loadstart', handleEvent);
reader.addEventListener('load', handleEvent);
reader.addEventListener('loadend', handleEvent);
reader.addEventListener('progress', handleEvent);
reader.addEventListener('error', handleEvent);
reader.addEventListener('abort', handleEvent);
}
function formatBytes(bytes, decimals = 2) {
if (!+bytes) return '0 Bytes'
const k = 1024
const dm = decimals < 0 ? 0 : decimals
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
}
function handleSelectedFile(file) {
const selectedFile = file;
eventLog.textContent = '';
if (selectedFile) {
eventLog.textContent = 'New file selection\n';
eventLog.textContent += `File Type: ${selectedFile.type}\n`;
// for debuging only
addListeners(reader);
// read in file data as byte array
reader.onload = async function (e) {
const zstd = await ZSTD();
parser.parseArrayBuffer(reader.result, zstd);
eventLog.textContent += `Found ${parser.files.length} files in archive\n`;
let zip = new JSZip();
parser.files.forEach(function (file, i) {
let sizeInfo = formatBytes(file.rawData.length);
eventLog.textContent += `File ${i}: ${file.fileName} with ${sizeInfo}\n`;
if (file.rawData.length > 0) {
zip.file(
file.fileName.replace(/^\/+/, ''),
file.rawData,
{ createFolders: true }
);
}
});
let zipFileName = selectedFile.name;
const idx = selectedFile.name.lastIndexOf('.');
if (idx > 0) {
// change extension to .zip
zipFileName = selectedFile.name.substr(0, idx) + '.zip';
} else {
// file is missing an extension
zipFileName += '.zip';
}
zip.generateAsync({ type: "blob", compression: "DEFLATE", platform: "UNIX" }).then(function (blob) {
saveAs(blob, zipFileName);
});
}
reader.readAsArrayBuffer(selectedFile);
}
}
function dragHover(e) {
e.stopPropagation();
e.preventDefault();
if (e.type === 'dragover') {
e.target.className = 'over';
} else {
e.target.className = '';
}
}
dropDiv.addEventListener('dragover', dragHover);
dropDiv.addEventListener('dragleave', dragHover);
dropDiv.addEventListener('drop', function (e) {
e.stopPropagation();
e.preventDefault();
e.target.className = '';
var file = e.dataTransfer.files[0];
handleSelectedFile(file);
});
fileInput.addEventListener('change', function(e) {
e.stopPropagation();
e.preventDefault();
var file = fileInput.files[0];
handleSelectedFile(file);
});
</script>
</body>
</html>