Skip to content
This repository was archived by the owner on May 17, 2022. It is now read-only.

Commit d31c220

Browse files
committed
Merge branch 'main' into release
2 parents b1881a8 + f26aa15 commit d31c220

File tree

4 files changed

+159
-84
lines changed

4 files changed

+159
-84
lines changed

BugReporter.py

Lines changed: 87 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,98 @@
11
import json
22
import subprocess
33
import logging
4-
from os.path import exists
5-
6-
class __reporter__:
7-
def __init__(self, data:dict):
8-
commit = subprocess.check_output(["git", "describe", "--always"]).strip().decode()
9-
if data.get('commit') == commit:
10-
self.data = data
11-
else:
12-
self.data = {'commit':commit, 'tags':dict(), 'bugs_count':0, 'build':'passing'}
13-
14-
def bug(self, tag, message=None, custom_prop={}):
15-
tags = self.data['tags']
16-
current_tag = tags.get(tag, {'count':0})
17-
current_tag['count'] += 1
18-
current_tag['message'] = message
19-
current_tag['custom-prop'] = custom_prop
20-
tags[tag] = current_tag
21-
self.data['bugs_count'] = len(tags)
22-
if len(tags):
23-
self.data['build']='failing'
4+
import os
245

256
class BugReporter:
26-
def __init__(self, file_path = 'bugs.json'):
27-
if exists(file_path):
28-
try:
29-
self.reports = json.load(open(file_path, encoding='utf8'))
30-
except Exception as ex:
31-
logging.exception(f'Exception while trying to parse "{file_path}".')
32-
logging.warning('skipping parse bugs file.')
33-
self.reports = dict()
34-
else:
35-
self.reports = dict()
7+
def __init__(self, file_path = 'bugs.json', use_git=True, git='git', git_source=None):
8+
self.commit = None
9+
self.git_source = git_source
10+
self.bugs = dict()
11+
self.build_state = 'passing'
12+
self.bugs_count = 0
13+
self.__update_data__()
14+
self.use_git = use_git
15+
self.git = git
16+
if use_git:
17+
self.get_git_info()
3618
self.file_path = file_path
19+
self.load_file(file_path)
20+
21+
def __update_data__(self):
22+
self.data={
23+
'commit':self.commit,
24+
'bugs':self.bugs,
25+
'build_state':self.build_state,
26+
'bugs_count':self.bugs_count
27+
}
28+
29+
def load_file(self, file_path):
30+
if os.path.exists(file_path):
31+
self.file_path = file_path
32+
data=dict()
33+
try:
34+
with open(file_path, encoding='utf-8') as f:
35+
data = json.load(f)
36+
except:
37+
logging.exception('Can not parse bugs file')
38+
return
39+
if self.use_git:
40+
#compare commit
41+
if self.commit != data.get('commit') or not data.get('commit'):
42+
return
43+
44+
self.bugs = data.get('bugs',dict())
45+
self.build_state = data.get('build_state','passing')
46+
self.bugs_count = data.get('bugs_count',0)
47+
self.__update_data__()
48+
3749

38-
def __call__(self, group):
39-
data = self.reports.get(group,dict())
40-
reporter = __reporter__(data)
41-
self.reports[group] = reporter.data
42-
return reporter
50+
def get_git_info(self):
51+
dir = os.path.dirname(__file__)
52+
if dir != '':
53+
os.chdir(dir)
54+
try:
55+
short_hash = subprocess.check_output([self.git, 'describe', '--always'], stderr=subprocess.STDOUT).strip().decode()
56+
self.commit = subprocess.check_output([self.git, 'rev-parse', short_hash], stderr=subprocess.STDOUT).strip().decode()
57+
except subprocess.CalledProcessError:
58+
logging.error('There was an error - command exited with non-zero code')
59+
return
60+
except:
61+
logging.exception('Unknown error')
62+
return
63+
64+
if not self.git_source:
65+
lines=[]
66+
try:
67+
lines = subprocess.check_output([self.git, 'remote', '-v'], stderr=subprocess.STDOUT).decode().strip().split('\n')
68+
except subprocess.CalledProcessError:
69+
logging.error('There was an error - command exited with non-zero code')
70+
return
71+
except:
72+
logging.exception('Unknown error')
73+
return
74+
#get first fetch remote
75+
for l in lines:
76+
r = l.split()
77+
if r[2] == '(fetch)':
78+
r = r[1]
79+
if r.endswith('.git'):
80+
r = r[:-4]
81+
self.git_source = r
82+
break
83+
self.__update_data__()
4384

85+
def bug(self, tag_name, message=None, **more):
86+
tag = self.bugs.get(tag_name,{'count':0,'message':None})
87+
tag['message'] = message
88+
tag['count']+=1
89+
tag.update(more)
90+
self.bugs[tag_name] = tag
91+
self.bugs_count = len(self.bugs)
92+
self.__update_data__()
93+
4494
def dump(self):
45-
json.dump(self.reports, open(self.file_path, 'w', encoding='utf8'), indent = 2, ensure_ascii = False)
95+
json.dump(self.data, open(self.file_path, 'w', encoding='utf8'), indent = 2, ensure_ascii = False)
4696

4797
def dumps(self):
48-
return json.dumps(self.reports, indent = 2, ensure_ascii = False)
98+
return json.dumps(self.data, indent = 2, ensure_ascii = False)

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<h1 align="center">Telegram RSS Bot</h1>
44
<p align="center">
55
<a href="http://de1.hashbang.sh:7191">
6-
<img alt="" src="https://img.shields.io/badge/dynamic/json?url=http://de1.hashbang.sh:7191/json&label=build&query=$.Telegram_RSS_Bot.build&color=white">
7-
<img alt="Reported bugs from pcworms_bot project" src="https://img.shields.io/badge/dynamic/json?url=http://de1.hashbang.sh:7191/json&label=Bugs+found&query=$.Telegram_RSS_Bot.bugs_count&color=red">
6+
<img alt="" src="https://img.shields.io/badge/dynamic/json?url=http://de1.hashbang.sh:7191/json&label=build&query=$.build_state&color=white">
7+
<img alt="Reported bugs from pcworms_bot project" src="https://img.shields.io/badge/dynamic/json?url=http://de1.hashbang.sh:7191/json&label=Bugs+found&query=$.bugs_count&color=red">
88
</a>
99
<a href="https://github.com/bsimjoo/Telegram-RSS-Bot/labels/bug">
1010
<img alt="Bug issue" src="https://img.shields.io/github/issues-raw/bsimjoo/Telegram-RSS-Bot/bug?color=red">
@@ -25,8 +25,8 @@
2525
</a>
2626
</p>
2727
<p align="center">
28-
A simple telegram bot that started for <a href="http://pcworms.blog.ir">pcworms.blog.ir</a> weblog that read RSS Feeds and send newest feed to all chats(in this article chats = [all PVs, all GPs and all channels]).
29-
Administrators can also send photos, markdown or simple text messages to chats.</p>
28+
A simple telegram bot that read RSS Feeds and send newest feed to all chats(in this article chats = [all PVs, all GPs and all channels]).
29+
Administrators can also send photos, html or simple text messages to chats and ...</p>
3030
</p>
3131

3232
## Owner

config-example.conf

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,45 @@
1+
# Telegram-RSS-Bot
2+
# wrote by BSimjoo https://github.com/bsimjoo/Telegram-RSS-Bot
13
[main]
2-
# in telegram use @botfather to create a bot and then paste token here
4+
# in telegram use @botfather to create a bot and then paste token here
35
token = your bot token
46

57
source = https://pcworms.blog.ir/rss/
68
language = en-us
79
strings-file = Default-strings.json
810
log-level = info
911

10-
# specify path of file based database [CRITICAL]
12+
# [CRITICAL] specify path of file based database
1113
db-path = db.lmdb
1214

13-
# uncomment to save logs to file instead of console output
14-
# log-file = log.log
15+
# uncomment to save logs to file instead of console output
16+
#log-file = log.log
17+
18+
#----- Bug reporter configurations -----
19+
20+
# bug reporter modes:
21+
# off Disable bug-reporter
22+
# offline Saves bugs in bugs-file
23+
# online Saves bugs in file and also runs a http server, you can configure
24+
# HTTP-server (using cherrypy) in [bug-reporter] section
25+
# if you're going to run bug-reporter in online mode, make sure you have cherrypy installed
26+
# or use "python3 -m pip install cherrypy" to install it
1527

1628
bug-reporter = off
17-
# bug reporter modes:
18-
# off Disable bug-reporter
19-
# offline Saves bugs in bugs-file
20-
# online Saves bugs in file and also runs a http server, you can configure
21-
# HTTP-server (using cherrypy) in [bug-reporter] section
22-
# if you're going to run bug-reporter in online mode, make sure you have cherrypy installed
23-
# or use "python3 -m pip install cherrypy" to install it
24-
# bugs file needed if bug-reporter is not off
29+
30+
# check below configurations if bug reporter is not off
31+
32+
# Specify cherrypy config file if running bugreporter in online mode
33+
#reporter-config-file = Bug-reporter.conf
34+
2535
bugs-file = ./bugs.json
26-
reporter-config-file = Bug-reporter.conf
36+
use-git = false
37+
38+
# use below configuration if using git
39+
40+
# if your git executable is not in environment path variable so uncomment and change line below:
41+
#git-path = /usr/bin/git
42+
43+
# Bug reporter can reach repository url automatically but you can set a custom.
44+
# this url will use in a fast link to where bug found (exception raisen)
45+
#git-source = https://github.com/bsimjoo/Telegram-RSS-Bot

main.py

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def __init__(
117117
self.source = source
118118
self.interval = self.__get_data__('interval', 5*60, data_db)
119119
self.__check__ = True
120-
self.reporter = bug_reporter if bug_reporter else None
120+
self.bug_reporter = bug_reporter if bug_reporter else None
121121

122122
def handle_edited_msg(u: Update, c:CallbackContext):
123123
#TODO: Handle editing messages
@@ -413,7 +413,7 @@ def preview(u: Update, c: CallbackContext):
413413
else:
414414
logging.error('UNKNOWN MSG TYPE FOUND\n'+str(msg))
415415
c.bot.send_message(self.ownerID, 'UNKNOWN MSG TYPE FOUND\n'+str(msg))
416-
self.reporter.bug('unknown type message in preview', 'UNKNOWN MSG TYPE FOUND\n'+str(msg))
416+
self.bug_reporter.bug('unknown type message in preview', 'UNKNOWN MSG TYPE FOUND\n'+str(msg))
417417

418418
if c.user_data.get('had-error'):
419419
c.user_data['last-message'] = u.message.reply_text(
@@ -854,7 +854,7 @@ def error_handler(update: object, context: CallbackContext) -> None:
854854
logging.error(msg = "Exception while handling an update:",
855855
exc_info = context.error)
856856

857-
if type(context.error) is type(NetworkError):
857+
if isinstance(context.error, NetworkError):
858858
return
859859

860860
# traceback.format_exception returns the usual python message about an exception, but as a
@@ -868,8 +868,8 @@ def error_handler(update: object, context: CallbackContext) -> None:
868868
lineno = f.lineno
869869
filename = os.path.basename(f.filename)
870870
exception_type = type(context.error).__name__
871-
if self.reporter:
872-
self.reporter.bug(f'L{lineno}@{filename}: {exception_type}',tb_string, {'line':lineno, 'file':filename})
871+
if self.bug_reporter:
872+
self.bug_reporter.bug(f'L{lineno}@{filename}: {exception_type}', tb_string, line=lineno, file=filename)
873873

874874
# Build the message with some markup and additional information about what happened.
875875
# You might need to add some logic to deal with messages longer than the 4096 character limit.
@@ -1125,12 +1125,15 @@ def idle(self):
11251125

11261126
if main_config.get('bug-reporter', 'off') in ('online', 'offline'):
11271127
import BugReporter
1128-
bug_reporter = BugReporter.BugReporter()
1129-
reporter = bug_reporter('Telegram_RSS_Bot')
1128+
bugs_file = main_config.get('bugs-file','bugs.json')
1129+
use_git = main_config.getboolean('use-git',False)
1130+
git = main_config.get('git-command','git')
1131+
git_source = main_config.get('git-source')
1132+
bug_reporter = BugReporter.BugReporter(bugs_file, use_git, git, git_source)
11301133

11311134
if main_config.get('bug-reporter') == 'online':
11321135
try:
1133-
import cherrypy #user can ignore installing this mudole just if doesn't need reporting on http
1136+
import cherrypy #user can ignore installing this module just if doesn't need reporting on http
11341137

11351138
class root:
11361139

@@ -1140,50 +1143,53 @@ def index(self):
11401143
<head>
11411144
<style>
11421145
html, body{
1143-
background-color: #17202a;
1146+
background-color: #1b2631;
11441147
color: #d6eaf8;
11451148
}
11461149
pre, ssh-pre{
11471150
width:80%;
11481151
max-height: 30%;
11491152
margin: auto;
1150-
background-color: #f39c12;
1151-
color: black;
1153+
background-color: #873600;
1154+
color: white;
11521155
border-radius: 10px;
11531156
padding: 10px;
11541157
overflow-x: auto;
11551158
white-space: pre-wrap;
11561159
word-wrap: break-word;
11571160
}
1161+
a:visited{
1162+
color: #a569bd
1163+
}
11581164
</style>
11591165
</head>
1160-
<body><h1>Bugs</h1><hr>
1161-
<p><b>What is this page?</b> This project uses a simple web
1162-
server to report bugs (exceptions) in a running application.
1163-
<p><b>What are groups?</b> Because of this project can be forked
1164-
so each fork can have its own bugs. Although it is sometimes
1165-
difficult to distinguish between original project bugs and forged
1166-
projects, groups are a simple way to separate these bugs.<p>'''
1167-
1168-
for group, reporter in bug_reporter.reports.items():
1169-
res+=f'<h2>Group: {group}</h2><hr>'
1170-
for tag, content in reporter['tags'].items():
1166+
<body><h1 style="background-color: #d6eaf8; border-radius:10px; color:black">🐞 Bugs</h1>
1167+
<p><b>What is this?</b> This project uses a simple web
1168+
server to report bugs (exceptions) in a running application.</p>
1169+
<h6><a href="/json">Show raw JSON</a></h6>'''
1170+
1171+
if bug_reporter.bugs_count:
1172+
res+=f'<h2>😔 {bug_reporter.bugs_count} bug(s) found</h2>'
1173+
for tag, content in bug_reporter.bugs.items():
11711174
link = ''
1172-
if 'file' in content['custom-prop']:
1173-
lineno = content['custom-prop']['line']
1174-
filename = content['custom-prop']['file']
1175+
if 'file' in content and bug_reporter.use_git:
1176+
lineno = content['line']
1177+
filename = content['file']
11751178
if os.path.exists(filename):
1176-
link = f' <a href="https://github.com/bsimjoo/Telegram-RSS-Bot/blob/main/{filename}#L{lineno}">🔸may be here: L{lineno}@{filename}</a></h3>'
1179+
link = f' <a href="{bug_reporter.git_source}/blob/{bug_reporter.commit}/{filename}#L{lineno}">🔸may be here: L{lineno}@{filename}</a></h3>'
11771180
res+=f'<h3>&bull;Tag: <kbd>"{tag}"</kbd> Count: {content["count"]} {link}</h3>'
1178-
res+=f'<pre>{content["message"]}</pre>'
1181+
if content["message"]:
1182+
res+=f'<pre>{content["message"]}</pre>'
1183+
else:
1184+
res+='<h1 align="center">😃 NO 🐞 FOUND 😉</h1>'
11791185

1180-
res+='<h3 align="center"><a href="/json">Raw JSON</a></h3></body></html>'
1186+
res+='</body></html>'
11811187
return res
11821188

11831189
@cherrypy.expose
11841190
@cherrypy.tools.json_out()
11851191
def json(self):
1186-
return bug_reporter.reports
1192+
return bug_reporter.data
11871193

11881194
conf = main_config.get('reporter-config-file','Bug-reporter.conf')
11891195
if os.path.exists(conf):
@@ -1209,7 +1215,7 @@ def json(self):
12091215
sys.exit()
12101216

12111217
bot_handler = BotHandler(token, main_config.get('source','https://pcworms.blog.ir/rss/'), env,
1212-
chats_db, data_db, strings, reporter)
1218+
chats_db, data_db, strings, bug_reporter)
12131219
bot_handler.run()
12141220
bot_handler.idle()
12151221
if bug_reporter:

0 commit comments

Comments
 (0)