forked from Dogo6647/r2chat
Compare commits
No commits in common. "master" and "master" have entirely different histories.
4 changed files with 54 additions and 211 deletions
|
|
@ -1 +0,0 @@
|
|||
{"v":"WL1","n":"bar","l":{"en":{"langname":"English","chat":"Chat","regusers":"Registered users","chlist":"Channel list","lchan":"Leave channel","insert":"Insert","emoticon":"Emoticon","gif":"GIF","status":"Status","statmes":"Status messages","onlinestat":"Online (All notifs)","inactstat":"Inactive (Pings only)","busystat":"Busy (No notifs)","offlinestat":"Appear offline","pref":"Preferences","prefl":"prefrences","help":"Help","user":"User","chans":"Channels","lseen":"Last seen","impmes":"Important message! ","save":"Save","cancel":"Cancel","btodef":"Back to defaults","interface":"Interface","ffam":"Font family","fsiz":"Font size","fthi":"Frame thickness","backc":"Background color","textc":"Text color","userc":"Username color","usernh":"Use {username} where you want\n your username to be.","joinm":"Join message","leavm":"Leave message","inacm":"Inactive message","busym":"Busy message","choose":"Choose..."}},"r":{"gb":"en","us":"en"},"d":"en"}
|
||||
109
r2chat.py
109
r2chat.py
|
|
@ -1,14 +1,15 @@
|
|||
import tkinter as tk
|
||||
from tkinter import scrolledtext, messagebox
|
||||
from tkinter import ttk, colorchooser, font as tkfont
|
||||
import os, sys, json, time, getpass, webbrowser, re, subprocess
|
||||
import os, sys, json
|
||||
from pathlib import Path
|
||||
import time
|
||||
import getpass
|
||||
from plyer import notification
|
||||
import pygame as media
|
||||
from random import randint
|
||||
import wlang
|
||||
|
||||
wlang.setlangfile('assets/internal/lang.json')
|
||||
import webbrowser
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
if sys.platform == "win32":
|
||||
ROOT = Path("C:/Users/Public")
|
||||
|
|
@ -17,8 +18,8 @@ else:
|
|||
|
||||
try:
|
||||
if sys.argv[1]!='chat':
|
||||
CHANCHAN = sys.argv[1].replace(' ','_').replace('.','-').replace('\\','/').replace(':','/')
|
||||
CHANNEL = 'chat_'+CHANCHAN.replace('/','#')
|
||||
CHANCHAN = sys.argv[1].replace(' ','_').replace('.','-')
|
||||
CHANNEL = 'chat_'+CHANCHAN
|
||||
else:
|
||||
CHANNEL = 'chat'
|
||||
CHANCHAN = 'chat'
|
||||
|
|
@ -48,12 +49,11 @@ DEFAULT_CONFIG = {
|
|||
"border_width": 2,
|
||||
"bg_color": "#f0f0f0",
|
||||
"fg_color": "#1e1e1e",
|
||||
"user_color": f"#{['0000ff','af0000','00af00','ffaf00','ff00ff','00ffff','7f00ff','ff7f00','00ff7f','007fff'][randint(0,9)]}",
|
||||
"user_color": "#0000ff",
|
||||
"status_join": "{username} is now online.",
|
||||
"status_leave": "{username} is now offline.",
|
||||
"status_inactive": "{username} will be right back.",
|
||||
"status_busy": "{username} is busy.",
|
||||
"language": "en"
|
||||
"status_busy": "{username} is busy."
|
||||
}
|
||||
|
||||
def load_config():
|
||||
|
|
@ -76,8 +76,8 @@ class r2chat:
|
|||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.cfg = load_config()
|
||||
self.root.title(f"r2chat :: {username} / #{CHANCHAN.replace('#','/')}")
|
||||
wlang.setlang(self.cfg['language'])
|
||||
self.root.title(f"r2chat :: {username} / #{CHANCHAN}")
|
||||
|
||||
self.last_size = 0
|
||||
|
||||
# configs
|
||||
|
|
@ -98,29 +98,28 @@ class r2chat:
|
|||
|
||||
## chat menu
|
||||
self.chatmenu = tk.Menu(self.menubar, tearoff=0)
|
||||
self.menubar.add_cascade(label=wlang.getobj('chat'), menu=self.chatmenu)
|
||||
self.chatmenu.add_command(label=wlang.getobj('regusers'), command=lambda: self.show_users())
|
||||
self.chatmenu.add_command(label=wlang.getobj('chlist'), command=lambda: self.show_channels())
|
||||
self.chatmenu.add_command(label=wlang.getobj('lchan'), command=lambda: self.on_close())
|
||||
self.menubar.add_cascade(label="Chat", menu=self.chatmenu)
|
||||
self.chatmenu.add_command(label="Registered users", command=lambda: self.show_users())
|
||||
self.chatmenu.add_command(label="Channel list", command=lambda: self.show_channels())
|
||||
self.chatmenu.add_command(label="Leave channel", command=lambda: self.on_close())
|
||||
|
||||
## insert menu
|
||||
self.chatmenu = tk.Menu(self.menubar, tearoff=0)
|
||||
self.menubar.add_cascade(label=wlang.getobj('insert'), menu=self.chatmenu)
|
||||
self.chatmenu.add_command(label=wlang.getobj('emoticon'), command=lambda: print(""))
|
||||
## its pronounced jif
|
||||
self.chatmenu.add_command(label=wlang.getobj('gif'), command=lambda: print(""))
|
||||
self.menubar.add_cascade(label="Insert", menu=self.chatmenu)
|
||||
self.chatmenu.add_command(label="Emoticon", command=lambda: print(""))
|
||||
self.chatmenu.add_command(label="GIF", command=lambda: print(""))
|
||||
|
||||
## status menu
|
||||
self.chatmenu = tk.Menu(self.menubar, tearoff=0)
|
||||
self.menubar.add_cascade(label=wlang.getobj('status'), menu=self.chatmenu)
|
||||
self.chatmenu.add_command(label=wlang.getobj('onlinestat'), command=lambda: self.setstatus("online"))
|
||||
self.chatmenu.add_command(label=wlang.getobj('inactstat'), command=lambda: self.setstatus("inactive"))
|
||||
self.chatmenu.add_command(label=wlang.getobj('busystat'), command=lambda: self.setstatus("busy"))
|
||||
self.chatmenu.add_command(label=wlang.getobj('offlinestat'), command=lambda: self.setstatus("offline"))
|
||||
self.menubar.add_cascade(label="Status", menu=self.chatmenu)
|
||||
self.chatmenu.add_command(label="Online (All notifs)", command=lambda: self.setstatus("online"))
|
||||
self.chatmenu.add_command(label="Inactive (Pings only)", command=lambda: self.setstatus("inactive"))
|
||||
self.chatmenu.add_command(label="Busy (No notifs)", command=lambda: self.setstatus("busy"))
|
||||
self.chatmenu.add_command(label="Appear offline", command=lambda: self.setstatus("offline"))
|
||||
|
||||
## menu buttons
|
||||
self.menubar.add_command(label=wlang.getobj('pref'), command=lambda: self.openprefs())
|
||||
self.menubar.add_command(label=wlang.getobj('help'), command=lambda: webbrowser.open_new_tab("https://forgejo.nishi.boats/Dogo6647/r2chat"))
|
||||
self.menubar.add_command(label="Preferences", command=lambda: self.openprefs())
|
||||
self.menubar.add_command(label="Help", command=lambda: webbrowser.open_new_tab("https://forgejo.nishi.boats/Dogo6647/r2chat"))
|
||||
|
||||
# MAIN MENU STUFFS
|
||||
self.entry = tk.Entry(root, relief='sunken', borderwidth=self.cfg["border_width"])
|
||||
|
|
@ -136,7 +135,7 @@ class r2chat:
|
|||
open(CHAT_FILE, "a").close()
|
||||
|
||||
self.update_chat()
|
||||
self.write_system_message(f'((#00af00 | ◉)) {self.cfg["status_join"]}')
|
||||
self.write_system_message(f'◉ {self.cfg["status_join"]}')
|
||||
|
||||
def on_close(self):
|
||||
self.write_system_message(f'◌ {self.cfg["status_leave"]}')
|
||||
|
|
@ -181,13 +180,13 @@ class r2chat:
|
|||
status = new_status
|
||||
|
||||
if status == "online":
|
||||
self.write_system_message(msg=f'((#00af00 | ◉)) {self.cfg["status_join"]}')
|
||||
self.write_system_message(msg=f'◉ {self.cfg["status_join"]}')
|
||||
elif status == "offline":
|
||||
self.write_system_message(msg=f'◌ {self.cfg["status_leave"]}')
|
||||
elif status == "inactive":
|
||||
self.write_system_message(msg=f'((#ffaf00 | ◍)) {self.cfg["status_inactive"]}')
|
||||
self.write_system_message(msg=f'◍ {self.cfg["status_inactive"]}')
|
||||
elif status == "busy":
|
||||
self.write_system_message(msg=f'((#af0000 | ◎)) {self.cfg["status_busy"]}')
|
||||
self.write_system_message(msg=f'◎ {self.cfg["status_busy"]}')
|
||||
|
||||
self.user_data["status"] = status
|
||||
self.save_userdata(self.user_data)
|
||||
|
|
@ -214,15 +213,15 @@ class r2chat:
|
|||
|
||||
def show_users(self):
|
||||
win = tk.Toplevel(self.root)
|
||||
win.title(wlang.getobj('regusers'))
|
||||
win.title("Registered users")
|
||||
win.geometry("420x320")
|
||||
|
||||
tree = ttk.Treeview(win, columns=("user", "status", "channels", "last_seen"), show="headings")
|
||||
|
||||
tree.heading("user", text=wlang.getobj('user'))
|
||||
tree.heading("status", text=wlang.getobj('status'))
|
||||
tree.heading("channels", text=wlang.getobj('chans'))
|
||||
tree.heading("last_seen", text=wlang.getobj('lseen'))
|
||||
tree.heading("user", text="User")
|
||||
tree.heading("status", text="Status")
|
||||
tree.heading("channels", text="Channels")
|
||||
tree.heading("last_seen", text="Last seen")
|
||||
|
||||
tree.column("user", width=80)
|
||||
tree.column("status", width=60, anchor="center")
|
||||
|
|
@ -251,7 +250,7 @@ class r2chat:
|
|||
def show_channels(self):
|
||||
win = tk.Toplevel(self.root)
|
||||
win.title("Channel list")
|
||||
win.geometry("600x320")
|
||||
win.geometry("200x320")
|
||||
|
||||
tree = ttk.Treeview(win, columns=("channel"), show="headings")
|
||||
tree.heading("channel", text="Channels")
|
||||
|
|
@ -276,7 +275,7 @@ class r2chat:
|
|||
tree.bind("<Double-1>", on_select)
|
||||
|
||||
def open_channel(self, channel):
|
||||
self.write_system_message(f"((#006fff | ⇄)) {username} is chatting in {channel.replace('#','/')}.")
|
||||
self.write_system_message(f"⇄ {username} is chatting in {channel}.")
|
||||
if sys.platform == "win32":
|
||||
subprocess.Popen(f'pythonw "{os.path.abspath(__file__)}" "{channel}"', shell=True)
|
||||
else:
|
||||
|
|
@ -318,7 +317,7 @@ class r2chat:
|
|||
try:
|
||||
current_size = os.path.getsize(CHAT_FILE)
|
||||
|
||||
if current_size != self.last_size:
|
||||
if current_size > self.last_size:
|
||||
with open(CHAT_FILE, "r", encoding="utf-8") as f:
|
||||
f.seek(self.last_size)
|
||||
new_data = f.read()
|
||||
|
|
@ -327,7 +326,7 @@ class r2chat:
|
|||
self.chat_area.config(state='normal')
|
||||
if f"@{username} " in new_data and not "---" in new_data and not status == "busy" and not status == "offline":
|
||||
media.mixer.Sound("assets/internal/ping.ogg").play()
|
||||
messagebox.showinfo(wlang.getobj('impmes'), new_data)
|
||||
messagebox.showinfo("Important message!", new_data)
|
||||
if self.root.wm_state() == 'iconic':
|
||||
if not f"@{username} " in new_data and not status == "busy" and not status == "inactive":
|
||||
notification.notify(title="r2chat", message=new_data)
|
||||
|
|
@ -348,7 +347,7 @@ class PreferencesWindow:
|
|||
self.on_save = on_save
|
||||
|
||||
self.win = tk.Toplevel(parent)
|
||||
self.win.title(f"r2chat {wlang.getobj('prefl')}")
|
||||
self.win.title("r2chat prefs")
|
||||
self.win.geometry("420x520")
|
||||
self.win.resizable(False, False)
|
||||
self.win.transient(parent)
|
||||
|
|
@ -367,16 +366,16 @@ class PreferencesWindow:
|
|||
btn_frame = tk.Frame(self.win)
|
||||
btn_frame.pack(fill=tk.X, padx=10, pady=(0, 10))
|
||||
|
||||
tk.Button(btn_frame, text=wlang.getobj('save'), width=10, command=self._save).pack(side=tk.RIGHT, padx=(4, 0))
|
||||
tk.Button(btn_frame, text=wlang.getobj('cancel'), width=10, command=self.win.destroy).pack(side=tk.RIGHT)
|
||||
tk.Button(btn_frame, text=wlang.getobj('btodef'), command=self._reset).pack(side=tk.LEFT)
|
||||
tk.Button(btn_frame, text="Save", width=10, command=self._save).pack(side=tk.RIGHT, padx=(4, 0))
|
||||
tk.Button(btn_frame, text="Cancel", width=10, command=self.win.destroy).pack(side=tk.RIGHT)
|
||||
tk.Button(btn_frame, text="Back to defaults", command=self._reset).pack(side=tk.LEFT)
|
||||
|
||||
def _build_appearance_tab(self, notebook):
|
||||
frame = tk.Frame(notebook)
|
||||
notebook.add(frame, text=wlang.getobj('interface'))
|
||||
notebook.add(frame, text="Interface")
|
||||
|
||||
# font family
|
||||
self._row(frame, 0, wlang.getobj('ffam'))
|
||||
self._row(frame, 0, "Font family")
|
||||
font_var = tk.StringVar(value=self.cfg["font_family"])
|
||||
self.vars["font_family"] = font_var
|
||||
families = sorted(tkfont.families())
|
||||
|
|
@ -384,34 +383,34 @@ class PreferencesWindow:
|
|||
font_combo.grid(row=0, column=1, padx=10, pady=6, sticky=tk.W)
|
||||
|
||||
# font size
|
||||
self._row(frame, 1, wlang.getobj('fsiz'))
|
||||
self._row(frame, 1, "Font size")
|
||||
size_var = tk.IntVar(value=self.cfg["font_size"])
|
||||
self.vars["font_size"] = size_var
|
||||
tk.Spinbox(frame, from_=7, to=24, textvariable=size_var, width=6).grid(row=1, column=1, padx=10, pady=6, sticky=tk.W)
|
||||
|
||||
# border width
|
||||
self._row(frame, 2, wlang.getobj('fthi'))
|
||||
self._row(frame, 2, "Frame thickness")
|
||||
bw_var = tk.IntVar(value=self.cfg["border_width"])
|
||||
self.vars["border_width"] = bw_var
|
||||
tk.Spinbox(frame, from_=0, to=6, textvariable=bw_var, width=6).grid(row=2, column=1, padx=10, pady=6, sticky=tk.W)
|
||||
|
||||
# color pickers
|
||||
for i, (key, label) in enumerate([
|
||||
("bg_color", wlang.getobj('backc')),
|
||||
("fg_color", wlang.getobj('textc')),
|
||||
("user_color", wlang.getobj('userc')),
|
||||
("bg_color", "Background color"),
|
||||
("fg_color", "Text color"),
|
||||
("user_color", "Username color"),
|
||||
], start=3):
|
||||
self._row(frame, i, label)
|
||||
self._color_picker_row(frame, i, key)
|
||||
|
||||
def _build_status_messages_tab(self, notebook):
|
||||
frame = tk.Frame(notebook)
|
||||
notebook.add(frame, text=wlang.getobj('statmes'))
|
||||
notebook.add(frame, text="Status messages")
|
||||
|
||||
tk.Label(frame, text=wlang.getobj('usernh'), fg="gray", font=("Lucida Console", 9)).grid(
|
||||
tk.Label(frame, text="Use {username} where you want your username to be.", fg="gray", font=("Lucida Console", 9)).grid(
|
||||
row=0, column=0, columnspan=2, padx=10, pady=(10, 4), sticky=tk.W)
|
||||
|
||||
for i, (key, label) in enumerate([("status_join", wlang.getobj('joinm')),("status_leave", wlang.getobj('leavm')),("status_inactive", wlang.getobj('inacm')),("status_busy", wlang.getobj('busym'))], start=1):
|
||||
for i, (key, label) in enumerate([("status_join", "Join message"),("status_leave", "Leave message"),("status_inactive", "Inactive message"),("status_busy", "Busy message")], start=1):
|
||||
self._row(frame, i, label)
|
||||
var = tk.StringVar(value=self.cfg[key])
|
||||
self.vars[key] = var
|
||||
|
|
@ -433,7 +432,7 @@ class PreferencesWindow:
|
|||
v.set(result[1])
|
||||
p.config(bg=result[1])
|
||||
|
||||
tk.Button(frame, text=wlang.getobj('choose'), command=pick, width=8).grid(row=row, column=1, padx=(44, 0), pady=6, sticky=tk.W)
|
||||
tk.Button(frame, text="Choose…", command=pick, width=8).grid(row=row, column=1, padx=(44, 0), pady=6, sticky=tk.W)
|
||||
|
||||
def _save(self):
|
||||
for key, var in self.vars.items():
|
||||
|
|
|
|||
100
r2chat_LEGACY.py
100
r2chat_LEGACY.py
|
|
@ -1,100 +0,0 @@
|
|||
import tkinter as tk
|
||||
from tkinter import scrolledtext
|
||||
import os
|
||||
import time
|
||||
import getpass
|
||||
from json import loads
|
||||
|
||||
CHAT_FILE = "C:/Users/Public/r2chat/chat.txt"
|
||||
REFRESH_INTERVAL = 1000
|
||||
|
||||
BORDER_WIDTH = 3
|
||||
THEMES = [['white','white','white','black','Basic'],['#000707','#002727','#001717','white','Aqua']]
|
||||
|
||||
username = getpass.getuser()
|
||||
CONFIG_FILE = f'C:/r2chat/legacy_config/{username}.r2cc'
|
||||
|
||||
if not os.path.exists(CONFIG_FILE):
|
||||
CFILE_C=open(CONFIG_FILE, "a")
|
||||
CFILE_C.write('0\n is now online.\n is now offline.')
|
||||
CFILE_C.close()
|
||||
|
||||
def conf_line(n):
|
||||
return((open(CONFIG_FILE).read()).split('\n')[n])
|
||||
|
||||
THEME = int(conf_line(0))
|
||||
JOIN_MESSAGE = conf_line(1)
|
||||
LEAVE_MESSAGE = conf_line(2)
|
||||
|
||||
class r2chat:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title(f"r2chat Legacy :: {username}")
|
||||
|
||||
self.last_size = 0
|
||||
|
||||
self.chat_area = scrolledtext.ScrolledText(root, wrap='word', font=("Lucida Console", 11), bg=THEMES[THEME][1], fg=THEMES[THEME][3], relief='groove', borderwidth=BORDER_WIDTH)
|
||||
self.chat_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
|
||||
self.chat_area.bind("<Key>", lambda e: "break")
|
||||
|
||||
self.entry = tk.Entry(root, font=("Lucida Console", 11), bg=THEMES[THEME][2], fg=THEMES[THEME][3], relief='groove', borderwidth=BORDER_WIDTH)
|
||||
self.entry.pack(padx=10, pady=(0, 10), fill=tk.X)
|
||||
self.entry.bind("<Return>", self.send_message)
|
||||
|
||||
if not os.path.exists(CHAT_FILE):
|
||||
open(CHAT_FILE, "a").close()
|
||||
|
||||
self.update_chat()
|
||||
self.write_system_message(f"{username}{JOIN_MESSAGE}")
|
||||
|
||||
def on_close(self):
|
||||
self.write_system_message(f"{username}{LEAVE_MESSAGE}")
|
||||
self.root.destroy()
|
||||
|
||||
def write_system_message(self, msg):
|
||||
line = f"---- {msg} ----\n"
|
||||
with open(CHAT_FILE, "a", encoding="utf-8") as f:
|
||||
f.write(line)
|
||||
|
||||
def send_message(self, event=None):
|
||||
msg = self.entry.get().strip()
|
||||
if msg:
|
||||
timestamp = time.strftime("%y/%m/%d %H:%M")
|
||||
line = f"[{timestamp}] {username} (legacy): {msg}\n"
|
||||
try:
|
||||
with open(CHAT_FILE, "a", encoding="utf-8") as f:
|
||||
f.write(line)
|
||||
except Exception as e:
|
||||
print("oh noes! ", e)
|
||||
|
||||
self.entry.delete(0, tk.END)
|
||||
|
||||
def update_chat(self):
|
||||
try:
|
||||
current_size = os.path.getsize(CHAT_FILE)
|
||||
|
||||
if current_size > self.last_size:
|
||||
with open(CHAT_FILE, "r", encoding="utf-8") as f:
|
||||
f.seek(self.last_size)
|
||||
new_data = f.read()
|
||||
self.last_size = current_size
|
||||
self.chat_area.config(state='normal')
|
||||
self.chat_area.insert(tk.END, new_data)
|
||||
self.chat_area.config(state='disabled')
|
||||
self.chat_area.yview(tk.END)
|
||||
|
||||
except Exception as e:
|
||||
print("oh noes! ", e)
|
||||
|
||||
self.root.after(REFRESH_INTERVAL, self.update_chat)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
app = r2chat(root)
|
||||
root.geometry("500x520")
|
||||
root.minsize(360, 520)
|
||||
root.attributes('-topmost', True)
|
||||
root.protocol("WM_DELETE_WINDOW", app.on_close)
|
||||
root.configure(bg=THEMES[THEME][0])
|
||||
root.mainloop()
|
||||
55
wlang.py
55
wlang.py
|
|
@ -1,55 +0,0 @@
|
|||
import locale
|
||||
import json
|
||||
|
||||
# default language file
|
||||
langfile='lang.json'
|
||||
|
||||
# error and shit
|
||||
try:
|
||||
langfilecon=open(langfile).read()
|
||||
except:
|
||||
print('wlang error:Language file not found, continuing execution. Make sure to set the language file!')
|
||||
|
||||
# default language
|
||||
lang='en'
|
||||
deflangfull=locale.getdefaultlocale()[0]
|
||||
deflang=deflangfull[3:len(deflangfull)].lower()
|
||||
|
||||
# functions
|
||||
def setlangfile(lfile):
|
||||
global langfile
|
||||
global langfilecon
|
||||
langfile=lfile
|
||||
langfilecon=open(langfile).read()
|
||||
|
||||
def setlang(l):
|
||||
global lang
|
||||
lang=l
|
||||
|
||||
# get the d, n and v values
|
||||
def getlangname():
|
||||
return json.loads(langfilecon)["n"]
|
||||
|
||||
def getlangver():
|
||||
return json.loads(langfilecon)["v"]
|
||||
|
||||
def getinlangdef():
|
||||
return json.loads(langfilecon)["d"]
|
||||
|
||||
# the big one
|
||||
def getobj(obj):
|
||||
# sssdfg
|
||||
obj=str(obj)
|
||||
# get the thing
|
||||
try:
|
||||
return json.loads(langfilecon)["l"][lang][obj]
|
||||
except:
|
||||
# else use replaced
|
||||
try:
|
||||
return json.loads(langfilecon)["l"][json.loads(langfilecon)["r"][lang]][obj]
|
||||
except:
|
||||
# else use default
|
||||
try:
|
||||
return json.loads(langfilecon)["l"][json.loads(langfilecon)["d"]][obj]
|
||||
except:
|
||||
return '{'+obj+'}' # give up
|
||||
Loading…
Add table
Add a link
Reference in a new issue