diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 77aebc1..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.DS_Store
-*~
-typogra*
-klasky*
-alas*
-ROY4L*
-dnmyt*
-directory*
-CarlWinslows*
-Coach*
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index ae2904b..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,29 +0,0 @@
- Jollo LNT license
- Version 1 - February 2015
-
- Copyright, 2015. JOLLO NET NA.
- The Jollo IRC Network.
-
- Vu, fare wanderer, confronted with raw, programmatic instruction
- dans la forme la plus pure. A hesitation, troubled to the terms
- qui ce license affirme. Par un voyage du explorer le mechanisme
- et ponder la fabrication. Voila! La remide: egress sans risque.
-
- Sans trace (Leave No Trace) via sept principales:
-
- 0. Modifique language en advance. L'Apposer Jollo LNT license
- with copies en distribuer.
-
- 1. Non responsible pour neglige programme du problematique.
-
- 2. Non sympathie pour neglige programme du problematique.
-
- 3. Non permission l'modifique under any circumstance.
-
- 4. Non permission distribution under any circumstance.
-
- 5. Respect les programmatic instructions.
-
- 6. Non interfere avec l'harmonie d'une amitie.
-
-
diff --git a/requirements.txt b/requirements.txt
index fe96e16..e69de29 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +0,0 @@
-httplib2==0.9
-simplejson==3.4.0
diff --git a/ytmnd.js b/ytmnd.js
index 2a0a2cb..ad26f42 100644
--- a/ytmnd.js
+++ b/ytmnd.js
@@ -1,25 +1,42 @@
-(function(){
- var hasWebKit = ('webkitAudioContext' in window) && !('chrome' in window)
- var context = new webkitAudioContext()
- var request = new XMLHttpRequest()
- var source
- request.open('GET', url, true)
- request.responseType = 'arraybuffer'
- request.onload = function() {
- context.decodeAudioData(request.response, function(response) {
- (function loop(){
- if (source) {
- source.start(0)
- setTimeout(loop, source.buffer.duration * 1000 - (source.buffer.duration < 2 ? 0 : 60) )
+(function () {
+ var AudioContext = window.AudioContext || window.webkitAudioContext;
+ var context = new AudioContext();
+ var request = new XMLHttpRequest();
+ var source;
+ var buffer;
+
+ request.open("GET", url, true);
+ request.responseType = "arraybuffer";
+
+ request.onload = function () {
+ context.decodeAudioData(
+ request.response,
+ function (response) {
+ buffer = response;
+
+ function playBuffer() {
+ source = context.createBufferSource();
+ source.buffer = buffer;
+ source.connect(context.destination);
+
+ source.onended = function () {
+ playBuffer();
+ };
+
+ source.start(0);
}
- else {
- setTimeout(loop, 0)
- }
- source = context.createBufferSource()
- source.connect(context.destination)
- source.buffer = response
- })()
- }, function () { console.error('The request failed.') } )
- }
- request.send()
-})()
+
+ playBuffer();
+ },
+ function (error) {
+ console.error("Audio decoding failed:", error);
+ },
+ );
+ };
+
+ request.onerror = function () {
+ console.error("Failed to load audio file");
+ };
+
+ request.send();
+})();
diff --git a/ytmnd.py b/ytmnd.py
index ade7b04..3e45f19 100755
--- a/ytmnd.py
+++ b/ytmnd.py
@@ -1,17 +1,19 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
import sys
import os
import os.path
import re
import time
-import urllib2
-import simplejson
+import json
+import subprocess
from optparse import OptionParser
+from urllib.request import urlopen, Request
+from urllib.error import URLError, HTTPError
class YTMND:
- def __init__ (self):
+ def __init__(self):
self.user_mode = False
self.media_only = False
self.html_only = False
@@ -20,64 +22,90 @@ class YTMND:
self.print_json = False
self.sleep = 5
- # Scrapes sites from the profile page, then fetches them
def fetch_user(self, user):
if user == "":
- print("expecting one ytmnd name, got "+str(sys.argv))
+ print("expecting one ytmnd name, got " + str(sys.argv))
+ return
+
+ ytmnd_name = user
+ try:
+ req = Request("http://ytmnd.com/users/" + ytmnd_name + "/sites",
+ headers={'User-Agent': 'Mozilla/5.0'})
+ with urlopen(req) as response:
+ ytmnd_html = response.read().decode('utf-8').splitlines()
+ except (URLError, HTTPError) as e:
+ print(f"Error fetching user page: {e}")
return
- ytmnd_name = user
- ytmnd_html = urllib2.urlopen("http://ytmnd.com/users/" + ytmnd_name + "/sites").readlines()
-
domains = []
-
+
for line in ytmnd_html:
if 'profile_link' in line:
expr = r"site_link\" href=\"http://(\S+).ytmn(d|sfw)?.com\""
- domain = re.search(expr,line).group(1)
- domains.append(domain)
+ match = re.search(expr, line)
+ if match:
+ domain = match.group(1)
+ domains.append(domain)
if self.json_only:
if self.media_only:
- os.system("mkdir -p %s" % user)
+ os.makedirs(user, exist_ok=True)
os.chdir(user)
parsed = []
for domain in domains:
- parsed.append( self.fetch_ytmnd( domain ) )
+ result = self.fetch_ytmnd(domain)
+ if result:
+ parsed.append(result)
if self.media_only:
os.chdir("..")
self.write_json(ytmnd_name, parsed)
else:
- print ">> found %d domains" % len( domains )
- os.system("mkdir -p %s" % user)
+ print(">> found %d domains" % len(domains))
+ os.makedirs(user, exist_ok=True)
os.chdir(user)
if not self.no_web_audio:
self.copy_ytmnd_js()
for domain in domains:
- self.fetch_ytmnd( domain )
+ self.fetch_ytmnd(domain)
os.chdir("..")
- # Fetches a single subdomain
def fetch_ytmnd(self, domain):
if domain == "":
- print("expecting one ytmnd name, got "+str(sys.argv))
- return
+ print("expecting one ytmnd name, got " + str(sys.argv))
+ return None
if not self.print_json:
- print "fetching %s" % domain
- if not self.sleep:
+ print("fetching %s" % domain)
+ if self.sleep:
time.sleep(self.sleep)
ytmnd_name = domain
- ytmnd_html = urllib2.urlopen("http://" + domain + ".ytmnd.com").read()
- expr = r"ytmnd.site_id = (\d+);"
- ytmnd_id = re.search(expr,ytmnd_html).group(1)
- ytmnd_info = simplejson.load(urllib2.urlopen("http://" + domain + ".ytmnd.com/info/" + ytmnd_id + "/json"))
+ try:
+ req = Request("http://" + domain + ".ytmnd.com",
+ headers={'User-Agent': 'Mozilla/5.0'})
+ with urlopen(req) as response:
+ ytmnd_html = response.read().decode('utf-8')
+
+ expr = r"ytmnd.site_id = (\d+);"
+ match = re.search(expr, ytmnd_html)
+ if not match:
+ print(f"Could not find site_id for {domain}")
+ return None
+ ytmnd_id = match.group(1)
+
+ req = Request("http://" + domain + ".ytmnd.com/info/" + ytmnd_id + "/json",
+ headers={'User-Agent': 'Mozilla/5.0'})
+ with urlopen(req) as response:
+ ytmnd_info = json.load(response)
+
+ except (URLError, HTTPError) as e:
+ print(f"Error fetching {domain}: {e}")
+ return None
if self.print_json:
- print simplejson.dumps(ytmnd_info, sort_keys=True, indent=4 * ' ')
+ print(json.dumps(ytmnd_info, sort_keys=True, indent=4))
elif self.json_only:
if self.media_only:
self.fetch_media(ytmnd_info)
@@ -92,28 +120,25 @@ class YTMND:
return ytmnd_info
- # Fetches the gif and mp3 for a post
def fetch_media(self, ytmnd_info):
domain = ytmnd_info['site']['domain']
original_gif = ytmnd_info['site']['foreground']['url']
gif_type = original_gif.split(".")[-1]
original_wav = ytmnd_info['site']['sound']['url']
wav_type = ytmnd_info['site']['sound']['type']
-
+
if 'alternates' in ytmnd_info['site']['sound']:
- key = ytmnd_info['site']['sound']['alternates'].keys()[0]
+ key = list(ytmnd_info['site']['sound']['alternates'].keys())[0]
value = ytmnd_info['site']['sound']['alternates'][key]
if value['file_type'] != 'swf':
original_wav = value['file_url']
wav_type = ytmnd_info['site']['sound']['file_type']
- os.system("wget --quiet -O %s %s" % (domain + "." + gif_type, original_gif))
- os.system("wget --quiet -O %s %s" % (domain + "." + wav_type, original_wav))
+ subprocess.run(["wget", "--quiet", "-O", f"{domain}.{gif_type}", original_gif])
+ subprocess.run(["wget", "--quiet", "-O", f"{domain}.{wav_type}", original_wav])
- # Writes an html file emulating the ytmnd format
def write_index(self, ytmnd_info):
-
- # print simplejson.dumps(ytmnd_info)
+
domain = ytmnd_info['site']['domain']
bgcolor = ytmnd_info['site']['background']['color']
title = ytmnd_info['site']['description']
@@ -122,93 +147,89 @@ class YTMND:
original_gif = ytmnd_info['site']['foreground']['url']
gif_type = original_gif.split(".")[-1]
wav_type = ytmnd_info['site']['sound']['type']
-
+
if 'alternates' in ytmnd_info['site']['sound']:
- key = ytmnd_info['site']['sound']['alternates'].keys()[0]
+ key = list(ytmnd_info['site']['sound']['alternates'].keys())[0]
value = ytmnd_info['site']['sound']['alternates'][key]
if value['file_type'] != 'swf':
original_wav = value['file_url']
wav_type = ytmnd_info['site']['sound']['file_type']
- fn = open(domain + ".html", 'w')
- fn.write("\n")
- fn.write("
\n")
- fn.write("%s\n" % title)
- fn.write("\n")
- fn.write("\n")
+ with open(domain + ".html", 'w', encoding='utf-8') as fn:
+ fn.write("\n")
+ fn.write("\n")
+ fn.write("%s\n" % title)
+ fn.write("\n")
+ fn.write("\n")
- fn.write("\n")
- self.write_zoom_text(fn, ytmnd_info)
-
- if self.no_web_audio:
- fn.write("